OpenAPI Nullable vs Null Value Explained in 3.0 and 3.1

OpenAPI nullable vs null value explained: Understand how nullable works in OpenAPI 3.0 and compare it with the null type in 3.1 for precise schema definitions.

Jump to section

Jump to section

Jump to section

When you're designing APIs and generating SDKs, getting `nullable` right in your OpenAPI specification directly impacts the quality and usability of your generated code. A poorly defined nullable property can lead to runtime errors, confusing type signatures, and SDKs that feel clunky to developers.

This guide explains how nullable works in OpenAPI 3.0 and 3.1, how it differs from optional properties, and how to use it effectively to generate clean, idiomatic SDKs across multiple programming languages. You'll learn the key distinctions between presence and nullability, see language-specific type outputs, and understand when to use nullable versus other patterns in your API design.
This guide explains how nullable works in OpenAPI 3.0 and 3.1, how it differs from optional properties, and how to use it effectively when you create OpenAPI specs for your API design and SDK generation.

What nullable means in OpenAPI specifications

In OpenAPI, nullable: true is a keyword you add to a schema property to indicate that its value can be null. It does not mean the property itself is a null type; rather, it’s a modifier that allows a defined type, like a string or number, to also accept null as a valid value. This is different from an optional property, which can be completely omitted from the request or response payload.

A nullable property must always be present in the JSON payload if it's also marked as required, but its value can be null. For example, a completed_at timestamp on a task could be nullable to signify a task that is not yet complete.

Here is a schema for a description property that must be a string:

description:
  type

And here is the same property, but now it can be either a string or null:

description:
  type: string
  nullable: true

How nullable works across OpenAPI versions

The way you define nullable properties changed between OpenAPI 3.0 and 3.1, which can be a common source of confusion. Understanding the difference is key to ensuring your spec is interpreted correctly by tooling.

Compare behavior in 3.0 and 3.1

OpenAPI 3.0 introduced the nullable: true boolean keyword to allow null values. OpenAPI 3.1 aligns more closely with the JSON Schema standard by instead including null as a possible value in the type array.

  • OpenAPI 3.0 Example:

    # A string that can also be null
    description:
      type: string
      nullable: true
  • OpenAPI 3.1 Example:

    # A string that can also be null
    description:
      type: ["string", "null"
    
    

Explain missing null type in 3.0

The OpenAPI 3.0 specification did not include null as a formal data type. The nullable keyword was created as a workaround to support this common use case without fully diverging from the JSON Schema specification at the time. This design choice meant that validation tools had to specifically check for the nullable keyword in addition to the type.

Handle x-nullable legacy extension

Before nullable was officially part of the OpenAPI 3.0 spec, some tools used a vendor extension called x-nullable. You might still encounter this in older or auto-generated specifications, particularly from Swagger 2.0. While modern tools should support the official nullable keyword, it's good to be aware of x-nullable if you're migrating a legacy API definition.

Make nullable schemas work

Applying nullable is straightforward once you know the pattern. Here are a few common examples of how to define nullable properties for different data structures.

Define simple nullable properties

For primitive types like strings, numbers, or booleans, you just add the nullable keyword.

  • Nullable String: A user's middle name might be optional.

    middle_name:
      type: string
      nullable: true
  • Nullable Integer: A score that hasn't been recorded yet.

    score:
      type: integer
      nullable: true

Define nullable objects and arrays

You can make an entire object or array nullable, or you can make the items within an array nullable.

  • Nullable Object: The metadata field could be null if no metadata is provided.

    metadata:
      type: object
      nullable: true
  • Nullable Array: A list of tags could be null.

    tags:
      type: array
      items:
        type: string
      nullable: true
  • Array of Nullable Items: A list of scores where some entries might be null.

    scores:
      type: array
      items:
        type: integer
        nullable: true

Combine nullable with $ref and formats

nullable works seamlessly with referenced schemas ($ref) and format specifiers. You apply nullable to the property that uses the reference, not within the referenced schema itself, unless you want every usage of that schema to be nullable.

properties:
  primary_address:
    $ref: '#/components/schemas/Address'
  secondary_address:
    $ref: '#/components/schemas/Address'
    nullable: true # secondary_address can be null

components:
  schemas:
    Address:
      type: object
      properties:
        street:
          type

Optional properties vs nullable properties

One of the most critical distinctions in API design is between a property that is optional and one that is nullable. They are not the same and solve different problems. An optional property can be omitted entirely, while a nullable property must be included (if required) but can have a value of null.

Map the four presence/value combinations

This table breaks down the four possible combinations for a property.

Combination

Is the key present?

Can the value be null?

Example Use Case

Required & Non-nullable

Always

No

A user's primary email.

Required & Nullable

Always

Yes

A completed_at timestamp on a task.

Optional & Non-nullable

Maybe

No

A limit parameter for pagination.

Optional & Nullable

Maybe

Yes

A note field that can be absent or explicitly cleared.

Choose the right combination

Choosing the right pattern depends on what you want to communicate.

  • Use required and nullable for fields that represent a state that can be explicitly "not set" or "cleared," like resetting a profile picture.

  • Use optional for fields that are not essential for an operation, like query parameters for filtering or sorting. This allows clients to send leaner payloads by omitting what they don't need.

How nullable affects SDK generation

How nullable is defined in your OpenAPI spec directly impacts the types and ergonomics of the SDKs generated from it. A well-defined spec leads to SDKs that feel intuitive and prevent common runtime errors, because your API isn't finished until the SDK ships.

See language-specific type output

Different programming languages have their own idiomatic ways of handling nullability, and a good SDK generator respects these conventions.

  • TypeScript: A nullable string becomes a union type: string | null.

  • Python: Type hints will use Optional[str], which means the value can be a str or None.

  • Go: Nullable fields are often represented as pointers, like *string, to distinguish between a zero value (empty string) and nil.

  • Java: Nullable types are commonly wrapped in java.util.Optional<String>, though making Java nullable fields backwards compatible requires careful consideration.

Trust Stainless to handle edge cases

Using a robust SDK generator ensures that nullable properties are correctly and idiomatically translated into strongly-typed code for each language, and lets you add custom code that persists through regeneration when you need specific modifications.

Use nullable wisely in API design

Just because you can make a property nullable doesn't always mean you should. Thoughtful use of nullability makes your API more predictable and easier for developers to use correctly.

Reserve nullable for meaningful absence

Use nullable when null conveys a specific, intentional business meaning. It's not just a missing value; it's a state.

  • Soft Deletes: A deleted_at timestamp is null for active records and has a date for deleted ones.

  • Unset Fields: In a PATCH request, sending {"middle_name": null} can explicitly clear a user's middle name, whereas omitting the key would leave it unchanged.

  • Incomplete Data: A processed_at field can be null until a background job completes.

Avoid nullable when defaults suffice

Sometimes, a default value is clearer and simpler than allowing null.

  • Empty String vs. Null: For a notes field, an empty string "" might be a better representation of "no notes" than null.

  • Zero vs. Null: For a retry_count, 0 is a more natural starting value than null.

  • Default Enum vs. Null: For a status field, having a default enum value like pending is often better than null.

Plan migration paths

Adding nullable: true to an existing, non-nullable property is generally a non-breaking change for clients. However, making a nullable property non-nullable is a breaking change. Plan your data models carefully to avoid forcing breaking changes on your users later.

Frequently asked questions about nullable in OpenAPI

Here are answers to some common questions developers have when working with nullable in OpenAPI specifications.

Can required fields be nullable?

Yes, absolutely. The required keyword controls whether a property's key must be present in the object, while nullable controls whether that property's value can be null.

How do I specify a nullable array with nullable items?

In OpenAPI 3.0, you would define the array with nullable: true and also set nullable: true on the items schema to allow null values inside the array.

What happens when nullable and default appear together?

If a property is nullable and also has a default value, the default is typically used only when the property key is omitted from the request, not when it is explicitly set to null.

How do I migrate nullable schemas from 3.0 to 3.1?

To migrate, you replace type: <some_type> and nullable: true with type: [<some_type>, "null"] for each relevant property in your specification. Using branches allows you to safely test these changes before merging to your main spec.

Do all SDK generators treat nullable the same?

No, support and interpretation can vary significantly between different code generation tools, which can lead to inconsistent or non-idiomatic SDKs that make it difficult to properly integrate docs with accurate code snippets.

Ready to generate high-quality, idiomatic SDKs from your OpenAPI spec? Get started for free.