An open API service indexing awesome lists of open source software.

https://github.com/techery/zod-to-openai-schema


https://github.com/techery/zod-to-openai-schema

Last synced: 4 months ago
JSON representation

Awesome Lists containing this project

README

          

# zod-to-openai-schema

[![npm version](https://badge.fury.io/js/@techery%2Fzod-to-openai-schema.svg)](https://www.npmjs.com/package/@techery/zod-to-openai-schema)
![CI Status](https://github.com/techery/zod-to-openai-schema/actions/workflows/pr-checks.yml/badge.svg?branch=main)

Convert [Zod](https://github.com/colinhacks/zod) schemas to [OpenAI function calling](https://platform.openai.com/docs/guides/function-calling) compatible JSON Schema. This library helps you define your OpenAI function parameters using Zod's powerful schema definition system.

Developed by [Techery](https://techery.io).

## Features
- Convert Zod schemas to OpenAI-compatible JSON Schema
- Preserves property descriptions and structure
- Full TypeScript support
- Zero dependencies (except Zod)

## Type Compatibility

| 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` |

## Installation

```bash
npm install zod-to-openai-schema
# or
yarn add zod-to-openai-schema
# or
pnpm add zod-to-openai-schema
```

## Usage

### Basic Example

```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
}
```

### Using with OpenAI Function Calling

```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),
},
],
});
```

### Advanced Examples

#### 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.lazy(() =>
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"
```

## Supported Features

- Basic Types:
- `string`
- `number` (with `int()` support)
- `boolean`

- Complex Types:
- Objects (`z.object()`)
- Arrays (`z.array()`)
- Enums (`z.enum()`)
- Unions (`z.union()`)
- Discriminated Unions (`z.discriminatedUnion()`)
- Literals (`z.literal()`)
- Recursive types (using `z.lazy()`)

- Modifiers:
- Nullable fields (`nullable()`)
- References (`$ref` and `$defs`)

- Metadata:
- Description preservation
- Custom type definitions

## Limitations

- 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

## API Reference

### `zodToOpenAISchema(schema: z.ZodTypeAny, config?: Config): OpenAIStructuredOutputSchema`

Converts a Zod schema into an OpenAI-compatible JSON Schema.

#### Config Options
```typescript
interface Config {
definitions?: Definition[];
}

interface Definition {
name: string;
schema: z.ZodObject;
}
```

### `definition(name: string, schema: z.ZodObject): Definition`

Helper function to create named type definitions for reuse.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Authors

- [Serge Zenchenko](https://github.com/sergezenchenko) - CTO at [Techery](https://techery.io)

## License

MIT