Capítulo 46 de 61
Zod's JSON Schema conversion maps each schema type to the JSON Schema mechanism that best represents it — format for well-known string shapes, pattern for the rest, additionalProperties for object strictness, and anyOf/type-arrays for nullability.
z.email(), z.iso.datetime(), z.iso.date(), z.iso.duration(), z.ipv4(), z.ipv6(), z.uuid(), z.guid(), z.url()) map to JSON Schema's format keyword; z.base64() maps to contentEncoding; everything else (z.iso.time(), z.base64url(), z.cuid(), z.emoji(), z.nanoid(), z.cuid2(), z.ulid(), z.cidrv4(), z.cidrv6(), z.mac()) falls back to a regex pattern.z.number() → {type: "number"}; z.float32()/z.float64() add exclusiveMinimum/exclusiveMaximum bounds; z.int() → {type: "integer"}; z.int32() adds the same exclusive bounds.additionalProperties: plain z.object() emits additionalProperties: false (matching its default strip behavior); z.looseObject() never sets it to false; z.strictObject() always sets it to false. In io: "input" mode, additionalProperties is omitted entirely.z.file(): converts to an OpenAPI-friendly { type: "string", format: "binary", contentEncoding: "binary" }, with .min()/.max()/.mime() adding minLength/maxLength/contentMediaType.z.null() → {type: "null"}. z.nullable(inner) adds "null" to the type set when inner is a bare type ({type: ["string", "null"]}), or falls back to anyOf when inner isn't representable as a bare type (e.g. it has its own constraints). z.optional() schemas convert to the inner type as-is, annotated as optional rather than changing the JSON Schema shape.z.email(); // => { type: "string", format: "email" }
z.base64(); // => { type: "string", contentEncoding: "base64" }
z.cuid(); // => { type: "string", pattern: "..." }
z.object({ name: z.string() });
// => { type: "object", properties: {...}, required: [...], additionalProperties: false }
z.file().min(1).max(1024 * 1024).mime("image/png");
// => { type: "string", format: "binary", contentEncoding: "binary",
// contentMediaType: "image/png", minLength: 1, maxLength: 1048576 }
z.nullable(z.string()); // => { type: ["string", "null"] }
z.nullable(z.string().min(5)); // => { anyOf: [{ type: "string", minLength: 5 }, { type: "null" }] }
anyOf versus a simple type array.| Zod construct | JSON Schema representation |
|---|---|
z.email(), z.iso.datetime(), z.url(), etc. | format keyword |
z.base64() | contentEncoding |
z.cuid(), z.ulid(), z.mac(), etc. | pattern (regex) |
z.object() (default) | additionalProperties: false |
z.looseObject() | additionalProperties never false |
z.strictObject() | additionalProperties always false |
z.null() | { type: "null" } |
anyOf rather than a simple type array — expect a more verbose JSON Schema in that case.additionalProperties — a quick way to audit whether a generated JSON Schema will reject unknown properties.format value — many fall back to a pattern regex, which is still functionally correct but less semantically labeled.z.toJSONSchema() entry point and its options.$defs.