Convert OpenAPI and TypeSpec definitions to Zod v4 validation schemas.
npm install @seiya8bit/otzotz is a command-line tool that generates Zod schemas from your OpenAPI definitions.
Maps OpenAPI types and formats to Zod schemas, and generates validation messages useful for UI forms.
| otz version | Zod version |
| ----------- | ----------- |
| 3.x | Zod v4 |
| 2.x | Zod v3 |
If you are using Zod v3, install the v2 release:
``sh`
npm install -D @seiya8bit/otz@2
- Node.js >= 22
`sh`
npm install -D @seiya8bit/otz
`sh`
otz -i path/to/openapi.yaml -o path/to/output.ts -c -p -q -n optional
- Type & Format Conversion: Translates OpenAPI type (e.g., integer) and format (e.g., email) properties into the appropriate Zod schema types.minimum
- Validation Rule Mapping: Converts OpenAPI validation keywords like , exclusiveMinimum, etc., into Zod validation checks (e.g., .min(), .max()).nullable: true
- Customizable Null Handling: Choose how properties are handled – map them to either .nullish() or .optional() in the generated Zod schemas.$ref
- Validation Message Generation: Option to automatically include validation messages within the generated Zod schemas, perfect for displaying feedback in forms.
- Split Definition Support: Seamlessly handles OpenAPI definitions that are split across multiple files using .
- Base types: string, number, bigint, boolean, date, symbol, undefined, null, void, any, unknown, neverobject
- Objects/arrays: -> z.object({ ... }), array -> z.array(...)z.enum([...])
- Enums: string enums -> ; non-string enums -> z.union([z.literal(...), ...])anyOf
- Unions: / oneOf -> z.union([...])allOf
- Composition: (object only) -> .merge(...)nullable: true
- Nullability: -> .nullish() or .optional() (configurable)default
- Defaults: -> .default(...) (bigint defaults for int64/uint64)minItems/maxItems
- Constraints: , minLength/maxLength, minimum/maximum (+ exclusive*) -> .min/.max/.gt/.gte/.lt/.ltepattern
- Regex: -> .regex(new RegExp(pattern))
- OpenAPI string formats:
- , uuid, uuidv4, uuidv6, uuidv7uri
- /url -> z.url()hostname
- , ipv4, ipv6, cidrv4, cidrv6byte
- -> z.base64(), base64url, nanoid, cuid, cuid2, ulid, guid, emojidate
- , time, date-time, duration -> z.iso.date/time/datetime/durationinteger
- OpenAPI number formats:
- -> z.int()int32
- , int64, uint32, uint64, float/float32, double/float64true
- additionalProperties: -> z.record(z.unknown()), false -> .strict(), schema -> .catchall(schema) or z.record(schema)
Run the otz command, specifying the input OpenAPI file, the desired output path, and any relevant options.
The following options are available for the otz command:
| Options | Description | Required | Default |
| --------------------- | ------------------------------------------------------------------- | -------- | -------- |
| -i, --input | Path to the root OpenAPI definition file (YAML or JSON). | ✅ | N/A |-o, --output
| | Output file path for the generated Zod schema. | ✅ | N/A |-c, --components
| | Generate schemas for definitions in components/schemas. | | false |-p, --paths
| | Generate schemas for request bodies and responses defined in paths. | | false |-q, --queries
| | Generate schemas for query parameters defined in paths. | | false |-n, --nullable-mode
| | Set null handling mode: nullish or optional. | | optional |
For OpenAPI definitions split across multiple files, specify the root file in the --input option.
- For OpenAPI users: See the OpenAPI Usage Guide for details on converting existing OpenAPI files.
- For TypeSpec users: See the TypeSpec Usage Guide for integrating otz` into your TypeSpec workflow.
- Petstore(basic)
- with Hono(advanced)
Contributions are welcome!
If you find a bug or have a feature request, feel free to open an issue or submit a pull request.
This project is licensed under the MIT License.