@gabrielbryk/json-schema-to-zod
v2.16.0
Published
Converts JSON schema objects or files into Zod schemas
Readme
Json-Schema-to-Zod
Notice of maintenance fork
The original package is being deprecated upstream, but this fork (https://github.com/gabrielbryk/json-schema-to-zod) continues maintenance and publishes to @gabrielbryk/json-schema-to-zod on npm.
Summary
A runtime package and CLI tool to convert JSON schema (draft 4+) objects or files into Zod schemas in the form of JavaScript code.
Before v2 it used prettier for formatting and json-refs to resolve schemas. To replicate the previous behaviour, please use their respective CLI tools.
Since v2 the CLI supports piped JSON.
Looking for the exact opposite? Check out zod-to-json-schema
Open issues
See open-issues.md for known correctness, type-safety, and performance gaps.
Usage
Online
Just paste your JSON schemas here!
CLI
Simplest example
npm i -g @gabrielbryk/json-schema-to-zodjson-schema-to-zod -i mySchema.json -o mySchema.tsExample with $refs resolved and output formatted
npm i -g @gabrielbryk/json-schema-to-zod json-refs prettierjson-refs resolve mySchema.json | json-schema-to-zod | prettier --parser typescript > mySchema.tsOptions
| Flag | Shorthand | Function |
| -------------- | --------- | ------------------------------------------------------------------------------------- |
| --input | -i | JSON or a source file path. Required if no data is piped. |
| --output | -o | A file path to write to. If not supplied stdout will be used. |
| --name | -n | The name of the schema in the output |
| --depth | -d | Maximum depth of recursion in schema before falling back to z.any(). Defaults to 0. |
| --type | -t | Export a named type along with the schema. Requires name to be set. |
| --noImport | -ni | Removes the import { z } from 'zod'; or equivalent from the output. |
| --withJsdocs | -wj | Generate jsdocs off of the description property. |
Programmatic
Simple example
import { jsonSchemaToZod } from "@gabrielbryk/json-schema-to-zod";
const myObject = {
type: "object",
properties: {
hello: {
type: "string",
},
},
};
const schemaCode = jsonSchemaToZod(myObject);
// `type` can be either a string or - outside of the CLI - a boolean. If its `true`, the name of the type will be the name of the schema with a capitalized first letter.
const moduleWithType = jsonSchemaToZod(myObject, {
name: "mySchema",
type: true,
});
const justTheSchema = jsonSchemaToZod(myObject);moduleWithType
import { z } from "zod";
export const mySchema = z.object({ hello: z.string().optional() });
export type MySchema = z.infer<typeof mySchema>;Naming customization
Use the naming option to control schema const names and exported type names (root + lifted refs).
const moduleWithCustomNaming = jsonSchemaToZod(myObject, {
name: "Workflow",
typeExports: true,
naming: {
schemaName: (base) => base,
typeName: (base) => `${base}Type`,
},
});Example with $refs resolved and output formatted
import { z } from "zod";
import { resolveRefs } from "json-refs";
import { format } from "prettier";
import jsonSchemaToZod from "@gabrielbryk/json-schema-to-zod";
async function example(jsonSchema: Record<string, unknown>): Promise<string> {
const { resolved } = await resolveRefs(jsonSchema);
const code = jsonSchemaToZod(resolved);
const formatted = await format(code, { parser: "typescript" });
return formatted;
}Overriding a parser
You can pass a function to the parserOverride option, which represents a function that receives the current schema node and the reference object, and should return a string when it wants to replace a default output. If the default output should be used for the node just return void.
Schema factoring
Factored schemas (like object schemas with "oneOf" etc.) is only partially supported. Here be dragons.
Use at Runtime
The output of this package is not meant to be used at runtime. JSON Schema and Zod does not overlap 100% and the scope of the parsers are purposefully limited in order to help the author avoid a permanent state of chaotic insanity. As this may cause some details of the original schema to be lost in translation, it is instead recommended to use tools such as Ajv to validate your runtime values directly against the original JSON Schema.
That said, it's possible in most cases to load the generated ESM with a data URL. Here's an example that you still probably shouldn't use:
const code = jsonSchemaToZod({ type: "string" }, { name: "mySchema" });
const { mySchema } = await import(`data:text/javascript,${encodeURIComponent(code)}`);
mySchema.safeParse("Please just use Ajv instead");