Skip to content

Instantly share code, notes, and snippets.

@rreusser
Last active April 8, 2024 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rreusser/6d89d9003ef3d6bd93633ff60ce3b4c8 to your computer and use it in GitHub Desktop.
Save rreusser/6d89d9003ef3d6bd93633ff60ce3b4c8 to your computer and use it in GitHub Desktop.

pydantic to zod

This repo demonstrates a simple pathway for going from pydantic to zod via JSON schema. To use, run:

python recipe.py > schema.json
npm run generate

The input is recipe.py containing a simple pydantic model, and the ouptut is recipe.ts, TypeScript zod schema.

{
"name": "pydantic-to-zod",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate": "json-refs resolve schema.json | json-schema-to-zod | prettier --parser typescript > schema.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"json-refs": "^3.0.15",
"json-schema-to-zod": "^2.0.14",
"prettier": "^3.2.5",
"zod": "^3.22.4"
}
}
import json
from typing import List
from pydantic import BaseModel, Field
class Layer(BaseModel):
name: str = Field(max_length=32, description="Layer name")
class Recipe(BaseModel):
tileset: str = Field(max_length=32, description="Name of the tileset")
minzoom: int = Field(ge=0, le=22, description="Minimum zoom")
maxzoom: int = Field(ge=0, le=22, description="Maximum zoom")
layers: List[Layer] = Field(description="Layers")
print(json.dumps(Recipe.model_json_schema(), indent=2))
{
"$defs": {
"Layer": {
"properties": {
"name": {
"description": "Layer name",
"maxLength": 32,
"title": "Name",
"type": "string"
}
},
"required": [
"name"
],
"title": "Layer",
"type": "object"
}
},
"properties": {
"tileset": {
"description": "Name of the tileset",
"maxLength": 32,
"title": "Tileset",
"type": "string"
},
"minzoom": {
"description": "Minimum zoom",
"maximum": 22,
"minimum": 0,
"title": "Minzoom",
"type": "integer"
},
"maxzoom": {
"description": "Maximum zoom",
"maximum": 22,
"minimum": 0,
"title": "Maxzoom",
"type": "integer"
},
"layers": {
"description": "Layers",
"items": {
"$ref": "#/$defs/Layer"
},
"title": "Layers",
"type": "array"
}
},
"required": [
"tileset",
"minzoom",
"maxzoom",
"layers"
],
"title": "Recipe",
"type": "object"
}
import { z } from "zod";
export default z.object({
tileset: z.string().max(32).describe("Name of the tileset"),
minzoom: z.number().int().gte(0).lte(22).describe("Minimum zoom"),
maxzoom: z.number().int().gte(0).lte(22).describe("Maximum zoom"),
layers: z
.array(z.object({ name: z.string().max(32).describe("Layer name") }))
.describe("Layers"),
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment