|
1 | 1 | --- |
2 | 2 | title: Null in OpenAPI best practices |
3 | | -description: Describing null values in OpenAPI schemas in OpenAPI 3.0.X and 3.1.X. |
| 3 | +description: Describing null values in OpenAPI schemas in OpenAPI 3.0.X and 3.1.X, including guidance on combining optional and nullable fields. |
4 | 4 | --- |
5 | 5 |
|
6 | 6 | # null in OpenAPI |
@@ -69,3 +69,88 @@ schema: |
69 | 69 | - type: 'null' |
70 | 70 | - type: string |
71 | 71 | ``` |
| 72 | + |
| 73 | +## Optional vs. nullable vs. optional + nullable |
| 74 | + |
| 75 | +In OpenAPI, **optional** and **nullable** are two separate concepts that are often confused: |
| 76 | + |
| 77 | +- **Optional** means a property can be omitted from the request or response body entirely. A property is optional when it is _not_ listed in the `required` array of its parent object. |
| 78 | +- **Nullable** means a property can be explicitly set to `null`. |
| 79 | + |
| 80 | +When a field is only **optional** (not required, not nullable), the API expects either a valid value or for the field to be omitted: |
| 81 | + |
| 82 | +```yaml |
| 83 | +# An optional string field (can be "hello" or omitted entirely) |
| 84 | +schema: |
| 85 | + type: object |
| 86 | + properties: |
| 87 | + nickname: |
| 88 | + type: string |
| 89 | +``` |
| 90 | + |
| 91 | +When a field is only **nullable** (required, but nullable), the API expects the field to always be present, but it can be set to `null`: |
| 92 | + |
| 93 | +```yaml |
| 94 | +# A required but nullable string field (can be "hello" or null, but must be present) |
| 95 | +# OpenAPI 3.0.X |
| 96 | +schema: |
| 97 | + type: object |
| 98 | + properties: |
| 99 | + nickname: |
| 100 | + type: string |
| 101 | + nullable: true |
| 102 | + required: |
| 103 | + - nickname |
| 104 | +
|
| 105 | +# OpenAPI v3.1 |
| 106 | +schema: |
| 107 | + type: object |
| 108 | + properties: |
| 109 | + nickname: |
| 110 | + type: ['null', 'string'] |
| 111 | + required: |
| 112 | + - nickname |
| 113 | +``` |
| 114 | + |
| 115 | +### When a field is both optional and nullable |
| 116 | + |
| 117 | +Marking a field as both optional _and_ nullable introduces three distinct states: |
| 118 | + |
| 119 | +| State | JSON representation | Meaning | |
| 120 | +| --- | --- | --- | |
| 121 | +| **Value present** | `{ "nickname": "hello" }` | The field is set to a value | |
| 122 | +| **Explicitly null** | `{ "nickname": null }` | The field is present but intentionally null | |
| 123 | +| **Omitted** | `{ }` | The field is not included at all | |
| 124 | + |
| 125 | +```yaml |
| 126 | +# An optional AND nullable field — three possible states |
| 127 | +# OpenAPI 3.0.X |
| 128 | +schema: |
| 129 | + type: object |
| 130 | + properties: |
| 131 | + nickname: |
| 132 | + type: string |
| 133 | + nullable: true |
| 134 | +
|
| 135 | +# OpenAPI v3.1 |
| 136 | +schema: |
| 137 | + type: object |
| 138 | + properties: |
| 139 | + nickname: |
| 140 | + type: ['null', 'string'] |
| 141 | +``` |
| 142 | + |
| 143 | +This is valid OpenAPI, but it adds real complexity for API consumers. SDK generators need to use special wrapper types to let users express all three states, since a simple pointer or `Optional` type can only distinguish between two states (set vs. unset). |
| 144 | + |
| 145 | +### When to use optional + nullable |
| 146 | + |
| 147 | +Only mark a field as both optional and nullable when the API genuinely treats `null` and omitted differently. Common examples include: |
| 148 | + |
| 149 | +- **PATCH endpoints** where omitting a field means "don't change this value" and sending `null` means "clear this value" |
| 150 | +- **Sparse update APIs** that distinguish between "no update" and "reset to default" |
| 151 | + |
| 152 | +### When to remove nullable from optional fields |
| 153 | + |
| 154 | +If the API treats `null` and omitted the same way, remove the `nullable` modifier and keep the field as just optional. Combining optional and nullable when they have the same effect is a common specification mistake that makes generated SDKs harder to use without any benefit. |
| 155 | + |
| 156 | +As a rule of thumb: if you can't describe a scenario where sending `{ "field": null }` and `{ }` should produce different outcomes, the field should be optional but **not** nullable. |
0 commit comments