|
1 | 1 | # Union Types |
2 | 2 |
|
3 | | -Union types in OpenAPI allow schemas to accept multiple different types or structures. The `oapi-codegen` generator handles `allOf`, `anyOf`, and `oneOf` with intelligent type generation based on the number and nature of the variants. |
| 3 | +Union types in OpenAPI allow schemas to accept multiple different types or structures. The `oapi-codegen` generator handles `allOf`, `anyOf`, `oneOf`, and `if`/`then`/`else` with intelligent type generation based on the number and nature of the variants. |
4 | 4 |
|
5 | 5 | ## Overview |
6 | 6 |
|
7 | 7 | - **`allOf`**: Merges all schemas into a single struct with all fields combined |
8 | 8 | - **`anyOf`**: Can match any of the specified schemas |
9 | 9 | - **`oneOf`**: Must match exactly one of the specified schemas |
| 10 | +- **`if`/`then`/`else`**: Conditional schemas (OpenAPI 3.1) - uses `runtime.Conditional[T, E]` |
10 | 11 |
|
11 | 12 | The generator applies smart optimizations based on the union structure: |
12 | 13 |
|
@@ -167,3 +168,83 @@ The `runtime.JSONMerge` function combines all the JSON parts into a single objec |
167 | 168 |
|
168 | 169 | [View complex union example](https://github.com/doordash-oss/oapi-codegen-dd/tree/main/examples/union/allof-anyof-oneof/){:target="_blank"} |
169 | 170 |
|
| 171 | +--- |
| 172 | + |
| 173 | +## Conditional Schemas (`if`/`then`/`else`) |
| 174 | + |
| 175 | +OpenAPI 3.1 supports JSON Schema conditional keywords. The generator |
| 176 | +treats `then` and `else` as structural branches. The `if` schema is |
| 177 | +ignored - it's a validation predicate (e.g. "if kind equals typeA") |
| 178 | +with no structural properties. `if` is also a reserved keyword in Go. |
| 179 | + |
| 180 | +### Both Branches - `runtime.Conditional` |
| 181 | + |
| 182 | +When both `then` and `else` are present, the generator creates a |
| 183 | +`runtime.Conditional[T, E]` wrapper with named variant types. Unlike |
| 184 | +`runtime.Either` (`.A`/`.B`), `Conditional` uses `.Then`/`.Else` |
| 185 | +fields and `.IsThen()`/`.IsElse()` methods. |
| 186 | + |
| 187 | +**OpenAPI Spec:** |
| 188 | + |
| 189 | +```yaml |
| 190 | +--8<-- "ifthenelse/basic/api.yaml:20:42" |
| 191 | +``` |
| 192 | + |
| 193 | +**Generated Go Code:** |
| 194 | + |
| 195 | +```go |
| 196 | +--8<-- "ifthenelse/basic/gen.go:16:19" |
| 197 | +``` |
| 198 | + |
| 199 | +The variant types use `_Then` and `_Else` suffixes: |
| 200 | + |
| 201 | +```go |
| 202 | +--8<-- "ifthenelse/basic/gen.go:86:98" |
| 203 | +``` |
| 204 | + |
| 205 | +Usage: |
| 206 | + |
| 207 | +```go |
| 208 | +if resource.Resource_IfThenElse.IsThen() { |
| 209 | + fmt.Println(resource.Resource_IfThenElse.Then.FieldA) |
| 210 | +} |
| 211 | +if resource.Resource_IfThenElse.IsElse() { |
| 212 | + fmt.Println(resource.Resource_IfThenElse.Else.FieldB) |
| 213 | +} |
| 214 | +``` |
| 215 | + |
| 216 | +[View basic example](https://github.com/doordash-oss/oapi-codegen-dd/tree/main/examples/ifthenelse/basic/){:target="_blank"} |
| 217 | + |
| 218 | +### Single Branch - Flat Merge |
| 219 | + |
| 220 | +When only `then` or only `else` is present, the branch properties |
| 221 | +are flat-merged into the parent struct. No wrapper type is created. |
| 222 | + |
| 223 | +**OpenAPI Spec:** |
| 224 | + |
| 225 | +```yaml |
| 226 | +--8<-- "ifthenelse/then-only/api.yaml:20:35" |
| 227 | +``` |
| 228 | + |
| 229 | +**Generated Go Code:** |
| 230 | + |
| 231 | +```go |
| 232 | +--8<-- "ifthenelse/then-only/gen.go:12:16" |
| 233 | +``` |
| 234 | + |
| 235 | +The `timeout` and `retries` fields from the `then` branch appear |
| 236 | +directly on the `Config` struct. |
| 237 | + |
| 238 | +[View then-only example](https://github.com/doordash-oss/oapi-codegen-dd/tree/main/examples/ifthenelse/then-only/){:target="_blank"} |
| 239 | + |
| 240 | +### With `$ref` Branches |
| 241 | + |
| 242 | +When `then`/`else` reference component schemas, the generated |
| 243 | +`Conditional` uses the referenced type names directly: |
| 244 | + |
| 245 | +```go |
| 246 | +--8<-- "ifthenelse/with-refs/gen.go:98:100" |
| 247 | +``` |
| 248 | + |
| 249 | +[View with-refs example](https://github.com/doordash-oss/oapi-codegen-dd/tree/main/examples/ifthenelse/with-refs/){:target="_blank"} |
| 250 | + |
0 commit comments