Convert Zod schemas to OpenAI structured output compatible schemas
npm install @techery/zod-to-openai-schema
!CI Status
Convert Zod schemas to OpenAI function calling compatible JSON Schema. This library helps you define your OpenAI function parameters using Zod's powerful schema definition system.
Developed by Techery.
| Zod Type | OpenAI Schema Type | Notes |
|----------|-------------------|-------|
| z.string() | string | Basic string type |
| z.number() | number | Floating point numbers |
| z.number().int() | integer | Integer numbers |
| z.boolean() | boolean | Boolean values |
| z.enum([...]) | string | With enum: [...] |
| z.object({...}) | object | With properties and required |
| z.array(...) | array | With items schema |
| z.union([...]) | N/A | Converted to anyOf: [...] |
| z.discriminatedUnion(...) | N/A | Converted to anyOf: [...] |
| z.literal(string) | string | With enum: [value] |
| z.null() | string | With enum: [null] |
| someSchema.nullable() | Same as base | With type: ['type', 'null'] |
| z.lazy(...) | Supported | Using $ref and $defs |
``bash`
npm install zod-to-openai-schemaor
yarn add zod-to-openai-schemaor
pnpm add zod-to-openai-schema
`typescript
import { z } from 'zod';
import { zodToOpenAISchema } from 'zod-to-openai-schema';
const schema = z.object({
name: z.string().describe('The name of the person'),
age: z.number(),
email: z.string().email(),
});
const jsonSchema = zodToOpenAISchema(schema);
// Resulting OpenAI schema:
{
type: "object",
properties: {
name: {
type: "string",
description: "The name of the person"
},
age: { type: "number" },
email: { type: "string" }
},
required: ["name", "age", "email"],
additionalProperties: false
}
`
`typescript
import { z } from 'zod';
import { zodToOpenAISchema } from 'zod-to-openai-schema';
import OpenAI from 'openai';
const createTodoSchema = z.object({
title: z.string().describe('The title of the todo item'),
priority: z.enum(['low', 'medium', 'high']).describe('Priority level'),
dueDate: z.string().describe('Due date in ISO format'),
});
const openai = new OpenAI();
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Create a high priority todo for reviewing code tomorrow' }],
functions: [
{
name: 'createTodo',
description: 'Create a new todo item',
parameters: zodToOpenAISchema(createTodoSchema),
},
],
});
`
#### Recursive Types with References
`typescript
import { z } from 'zod';
import { zodToOpenAISchema, definition } from 'zod-to-openai-schema';
// Define a recursive comment schema
const commentSchema: z.ZodType
z.object({
text: z.string(),
replies: z.array(commentSchema)
})
);
const schema = z.object({
post: z.object({
title: z.string(),
content: z.string(),
}),
comments: z.array(commentSchema)
});
const jsonSchema = zodToOpenAISchema(schema);
// Resulting schema will use $ref and $defs for recursive types
`
#### Reusable Types with Named Definitions
`typescript
const todoItemSchema = z.object({
name: z.string(),
completed: z.boolean(),
});
const schema = z.object({
pending: z.array(todoItemSchema),
completed: z.array(todoItemSchema),
});
const jsonSchema = zodToOpenAISchema(schema, {
definitions: [definition('TodoItem', todoItemSchema)],
});
// Resulting schema will use $ref: "#/$defs/TodoItem"
`
- Basic Types:
- stringnumber
- (with int() support)boolean
- z.object()
- Complex Types:
- Objects ()z.array()
- Arrays ()z.enum()
- Enums ()z.union()
- Unions ()z.discriminatedUnion()
- Discriminated Unions ()z.literal()
- Literals ()z.lazy()
- Recursive types (using )
- Modifiers:
- Nullable fields (nullable())$ref
- References ( and $defs)
- Metadata:
- Description preservation
- Custom type definitions
- Optional fields are not supported (OpenAI requires explicit handling of optional fields)
- Some Zod types are not supported:
- z.any()z.never()
- z.intersection()
- z.tuple()
- z.record()
-
- Validation constraints (min, max, regex, etc.) are not included in the output schema
Converts a Zod schema into an OpenAI-compatible JSON Schema.
#### Config Options
`typescript
interface Config {
definitions?: Definition[];
}
interface Definition {
name: string;
schema: z.ZodObject
}
``
Helper function to create named type definitions for reuse.
Contributions are welcome! Please feel free to submit a Pull Request.
- Serge Zenchenko - CTO at Techery
MIT