Handle Nullable Fields in Zod Schemas from JSON

Learn how to generate Zod schemas with .nullable() for fields that can be null in JSON. Understand the difference between nullable and optional in Zod.

Nested Objects

Detailed Explanation

Nullable Fields in Zod

JSON explicitly supports null as a value. Zod's .nullable() modifier allows a field to accept null in addition to its base type.

Example JSON

{
  "id": 1,
  "name": "Alice",
  "email": "alice@example.com",
  "deletedAt": null,
  "lastLoginAt": null,
  "avatar": null
}

Generated Zod Schema (with nullable toggle)

import { z } from "zod";

const userSchema = z.object({
  id: z.number().int().nullable(),
  name: z.string().nullable(),
  email: z.string().nullable(),
  deletedAt: z.null().nullable(),
  lastLoginAt: z.null().nullable(),
  avatar: z.null().nullable(),
});

type User = z.infer<typeof userSchema>;

Practical Pattern: Nullable Dates

A common pattern in APIs is date fields that are null when not yet set:

const taskSchema = z.object({
  id: z.number(),
  title: z.string(),
  createdAt: z.string(),
  completedAt: z.string().nullable(), // null when not completed
  deletedAt: z.string().nullable(),   // null when not deleted
});

nullable() vs null()

  • z.null() only accepts the value null — nothing else.
  • z.string().nullable() accepts either a string or null.
  • This distinction matters when a field is always null in your sample but could be a string in production.

Combining with .optional()

// Field can be: string, null, or absent entirely
z.string().nullable().optional()

// Field can be: string or absent (but not null)
z.string().optional()

// Field can be: string or null (but must be present)
z.string().nullable()

Nullish Shorthand

Zod provides .nullish() as shorthand for .nullable().optional():

// These are equivalent:
z.string().nullable().optional()
z.string().nullish()

Use .nullish() when a field can be null, undefined, or the base type — a common pattern with SQL databases where columns can be NULL and ORM queries may omit unselected fields.

Use Case

Your database returns user records where soft-deleted rows have a non-null deletedAt timestamp, and you need a schema that correctly validates both active (null) and deleted (string) states.

Try It — JSON to Zod Schema

Open full tool