Nullable fields in schemas: OpenAPI 3.1.0 type arrays vs nullable

Premium Deals
Mighty Travels Premium
Travel in style,
save up to 90%

On flights and hotels worldwide by booking the best deals when they appear.

See Deals

Sponsored

TakeawayDetail
OpenAPI 3.1.0 documents must use type arrays for nullabilityFor openapi: 3.1.0, express nullability with type: [string, 'null'] and never with nullable: true, because 3.1 tooling may silently ignore the legacy keyword.
OpenAPI 3.0.x documents must use nullable: trueFor documents pinned to 3.0.x, use nullable: true and never type arrays, since type-array syntax is the 3.1 form.
BigQuery JSON schemas can declare NULLABLE, REPEATED, or RECORD modesUsing a JSON file, you can specify descriptions, NULLABLE or REPEATED modes, and RECORD types for new columns.
Spark schemas cannot impose nullability unsupported by the data sourceIf a data source's semantics do not support nullability constraints, schema application cannot either; assume fields can be null rather than fail at runtime.

This guide explains how to express nullable fields correctly across OpenAPI versions and related schema systems.

It gives version-specific rules, migration cautions, and practical checks for avoiding ignored nullability declarations.

Nullable fields in schemas

How type arrays and nullable actually differ

In OpenAPI 3.1.0, the Schema Object is aligned with JSON Schema 2020-12, so the type keyword may be either a single string or an array of strings. Writing type: [string, 'null'] places null in the same type constraint as the primary type; the schema therefore permits a null value as part of its native type declaration. Stainless, in "OpenAPI Nullable vs Null Value Explained in 3.0 and 3.1," presents this array form as the 3.1 pattern for nullable schemas.

The nullable: true keyword has a different origin. It was introduced in OpenAPI 3.0 because that version's Schema Object was a restricted subset of JSON Schema, and OpenAPI needed its own way to say that a value could be null. Because nullable is not part of JSON Schema 2020-12, it is not a recognized keyword in a strict 3.1 Schema Object. A validator or generator that applies JSON Schema semantics may treat an unrecognized keyword as inert, so the field can be read as non-nullable even though the document says otherwise.

The divergence is therefore structural, not cosmetic. A type array changes the set of values the schema accepts: type: [string, 'null'] says both string and null are valid. nullable: true instead attaches a separate boolean flag to a schema whose base type does not include null. In 3.0 that flag is meaningful because the specification defines it; in 3.1 the same flag has no JSON Schema meaning unless a tool adds OpenAPI-specific handling.

This also affects how combinations are expressed. A type array can list several concrete types plus 'null', such as type: [string, integer, 'null'], while nullable: true can only toggle nullability on one base type. When reviewing a 3.1 document, check that nullability is visible inside the type array rather than in a sibling nullable key; if the latter remains, assume it may be ignored until the tooling proves otherwise.

How type arrays and nullable actually differ — Nullable fields in schemas

The evidence: what the sources actually say

The named sources on nullability handling are Stainless's OpenAPI explainer (stainless.com), Zod's schema documentation (zod.dev; app.studyraid.com), and the schema-system notes from BigQuery, Spark, and Valibot listed in the grounding. For the mechanism comparison, the option table, and migration steps, see the earlier and later sections of this guide.

Stainless's explainer states the pattern directly: "Applying nullable is straightforward once you know the pattern" for 3.0, and 3.1 uses type arrays; the two are not interchangeable across versions (stainless.com). That sentence is the version-boundary evidence: it presents 3.0 nullable handling as a pattern to learn and 3.1 handling as a different construct, rather than as two spellings of the same rule.

Zod documents .nullable() as a method that "modifies an existing schema to also accept null as a valid value," and separately documents .nullish() as "both optional and nullable" (zod.dev; app.studyraid.com). Those two definitions make nullability and optionality visible as distinct axes: one concerns whether null is accepted, while the other also concerns whether omission is accepted.

The implication for OpenAPI is that a single boolean cannot express both axes at once. A field can accept null without being optional, or be optional without accepting null, and those are different validation outcomes. Where the schema language supports a type-level union, nullability should be expressed there; where it does not, the version's documented keyword remains the appropriate construct. Stainless's version split and Zod's axis split point in the same direction without requiring the same syntax in both versions.

Read together, the sources support a narrow conclusion: match the nullability construct to the declared OpenAPI version, and do not treat nullable: true and type arrays as interchangeable syntax. Stainless supplies the version-specific pattern; Zod supplies the conceptual separation between accepting null and being optional.

Options compared: type arrays vs nullable

When deciding how to express a nullable field, start with the document's declared OpenAPI version rather than team preference. The comparison below names a winner for each version and gives the validator-facing reason for that choice.

For an openapi: 3.1.0 document, the winner is a type array such as type: [string, 'null']. It is the only form that JSON Schema 2020-12 validators are guaranteed to enforce, while the legacy nullable: true keyword is a 3.0-only construct that 3.1 tooling may silently ignore.

For an openapi: 3.0.x document, the winner is nullable: true. A 3.0 validator does not recognize a type array as a nullability declaration and will reject or mis-handle it, so the legacy keyword remains the compatible choice.

SyntaxSpec versionJSON Schema alignmentValidator behaviorRecommended when
type: [string, 'null']3.1.0JSON Schema 2020-12 type arrayEnforced as a type constraintDocument declares openapi: 3.1.0
nullable: true3.0.xOpenAPI 3.0 extension keywordRecognized by 3.0 validators; may be ignored by 3.1 toolingDocument declares openapi: 3.0.x

Use the table as a version gate: choose the row whose spec version matches the document's openapi field, and do not mix the two syntaxes in the same document. If a validator supports both versions, run it against the declared version before treating either syntax as accepted.

A useful review check is to search the document for both nullable: true and type arrays containing 'null'. If both appear, the document is internally inconsistent for its declared version and should be corrected before generation or validation.

Stainless's OpenAPI guidance presents nullable schemas as a pattern to apply deliberately, which supports treating nullability syntax as a compatibility decision rather than a stylistic preference.

Costs and numbers that matter

The expensive failure is silent: one unenforced nullable constraint per field, multiplied across every consumer that generates code from the schema. The grounding does not document how any specific generator treats an ignored nullability keyword, so treat the runtime risk as unverified until tested: feed your toolchain a minimal 3.1.0 schema with nullable: true, then exercise a null payload in the generated client and record whether it fails before relying on either syntax.

Migration cost is countable rather than structural. Every nullable: true occurrence in a 3.0 document must be rewritten as a type array, and because the count is directly greppable, effort scales with occurrences rather than with document size or nesting depth. A repository-wide search gives the work estimate before anyone edits a file.

Dual maintenance adds a second, ongoing cost. Keeping both keywords in one document creates two declarations of the same nullability intent, so reviewers must verify which declaration each tool reads and prevent drift between the two representations. That review repeats for every schema change until one syntax is removed.

The sources also do not resolve what happens when a document declares openapi: 3.1.0 but is consumed by tooling that supports only 3.0.x. That mismatch is an edge case rather than a rule: a parser may reject the document, coerce fields, or pass unknown keywords through. Test it per tool by comparing a schema using type: [string, 'null'] with an otherwise identical schema using nullable: true, then inspect generated types, validation output, and runtime acceptance.

Finally, the cited sources do not cover OpenAPI 3.2 or later. If your document declares a newer version, do not assume the 3.1 nullability rule carries over unchanged. Check that version's specification and your tooling's release notes before selecting syntax, and keep the declared version and nullability syntax aligned while the evidence remains limited to 3.0.x and 3.1.0.

Where the evidence stops, the safe practice is method-based: pin the OpenAPI version you target, avoid unsupported percentages, and verify behavior with small, repeatable schema tests rather than assumptions.

Migrating one field

Start with a 3.0.3 document in which middleName is declared as type: string with nullable: true. Keep the migration scoped to that one field: leave paths, components, and every other schema unchanged until both checkpoints pass, so a failure can be traced to one edit.

Checkpoint 1 is the version bump. Change the root openapi value from 3.0.3 to 3.1.0, then scan the entire document for 3.0-only keywords whose shape changed in 3.1. A common example is exclusiveMinimum written as a boolean in 3.0; in 3.1 it must be a number. Do not treat the version bump as a conversion step. If any such keyword remains, fix it before touching middleName.

Checkpoint 2 rewrites the field. Remove nullable: true from middleName and change type: string to type: [string, 'null']. Do not leave both forms in the same field; one nullability expression is enough. Keep the field in the same required or optional position it had before; nullability syntax does not decide whether the key is required. If middleName was optional, it stays optional, and if it was required, it stays required.

BeforeAfter
openapi: 3.0.3
middleName:
  type: string
  nullable: true
openapi: 3.1.0
middleName:
  type: [string, 'null']

Verify with three checks: the root declares 3.1.0; middleName has no nullable key; and its type is an array containing both string and 'null'. Also confirm that no neighboring field changed required or optional status during the edit. Stainless describes nullable schemas as straightforward once the pattern is known; the pattern to retain is version-specific, with nullable: true reserved for 3.0.x documents and type arrays reserved for 3.1.0 documents.

If checkpoint 1 fails, revert only the version bump and leave middleName unchanged. If checkpoint 2 fails, revert the field edit, but keep the version bump only after every 3.0-only keyword has been corrected. If a validator or generator still reads middleName as non-nullable after these checks, compare the tool's supported OpenAPI version with the document's declared version before changing the schema again.

Worked Example: Run the Numbers

Illustration only: consider one OpenAPI 3.1.0 document with one string field, email, that may be null. The two candidate expressions are type: [string, 'null'] and type: string with nullable: true. The only inputs are the schema text and one null value; no date, customer, or vendor is involved. No production metrics are used; the calculation counts only schema keywords and accepted JSON values.

Step 1 counts allowed types in the type-array expression: two members means two allowed JSON types, string and null. Step 2 counts the legacy keyword's effect in the second expression: under a 3.1.0 Schema Object, nullable is not part of the type constraint, so its contribution to the allowed-type count is zero. Step 3 tests a null payload: the first expression accepts null because null is one of the two counted types; the second accepts null only if another layer interprets the ignored keyword.

Frequently Asked Questions

What risk exists when an OpenAPI 3.1.0 document uses nullable: true?

3.1 tooling may silently ignore the legacy keyword.

Why should OpenAPI 3.0.x documents avoid type arrays for nullability?

Type-array syntax is the 3.1 form, so 3.0.x documents should use nullable: true instead.

Which modes can a BigQuery JSON schema declare for new columns?

Using a JSON file, you can specify descriptions, NULLABLE or REPEATED modes, and RECORD types for new columns.

What should a Spark schema do when the underlying data source does not support nullability constraints?

Assume fields can be null rather than fail at runtime.

How does OpenAPI 3.1.0's Schema Object relate to JSON Schema?

In OpenAPI 3.1.0, the Schema Object is aligned with JSON Schema 2020-12, so the type keyword may be either a single string or an array of strings.

What does writing type: [string, 'null'] accomplish in OpenAPI 3.1.0?

It places null in the same type constraint as the primary type.

Quick answers

How should nullability be expressed in OpenAPI 3.1.0?For openapi: 3.1.0, express nullability with type: [string, 'null'] and never with nullable: true.
How should nullability be expressed in OpenAPI 3.0.x?For documents pinned to 3.0.x, use nullable: true and never type arrays, since type-array syntax is the 3.1 form.
Why should OpenAPI 3.1.0 avoid nullable: true?3.1 tooling may silently ignore the legacy keyword.
What modes can BigQuery JSON schemas declare?BigQuery JSON schemas can declare NULLABLE, REPEATED, or RECORD modes.
What nullability limitation applies to Spark schema application?Spark schemas cannot impose nullability unsupported by the data source.

Also worth reading: OpenAPI 4.0's nullable: A Parse Failure Disguised as Spec Upgrade: OpenAPI 4.0's nullable: A Parse · OpenAPI 3: One Nullable Keyword Deleted, Three Encodings Win: OpenAPI 3: One Nullable Keyword · A Deep Dive into Snowpal's 7 API Licensing Models From Pay-Per-Request to Custom Infrastructure Solutions: Deep Dive into Snowpal's 7

Premium Deals
Mighty Travels Premium
Travel in style,
save up to 90%

On flights and hotels worldwide by booking the best deals when they appear.

See Deals

Sponsored

Research Methodology & Editorial Standards

We begin by defining the specific objectives the reader needs to accomplish. Primary product documentation and authoritative secondary sources are assembled into a verified research corpus; drafting occurs only after this foundation is in place.

Every quantitative claim is subjected to dual-source verification. Any figure that cannot be independently corroborated is either qualified or omitted.

Published · Last reviewed · Owned by the Specswriter editorial desk (About, Contact, Privacy).

Related answers