Many libraries can convert a schema into a JSON Schema, so it can be consumed by anything that speaks JSON Schema - documentation generators, OpenAPI builders, LLM structured outputs.
We benchmark whichever API the library provides, using a small schema with a codec. Libraries that generate JSON schemas at build time (e.g. typia) are not included — there's nothing to time at runtime.
Copy to clipboardconst schema = z.object({ id: z.number(), name: z.string(), price: z.codec( z.string(), z.number(), { decode: Number, encode: String }, ), }); const jsonSchema = z.toJSONSchema(schema);
Copy to clipboardconst schema = z.object({ id: z.number(), name: z.string(), price: z.codec(z.string(), z.number(), { decode: Number, encode: String, }), }); const jsonSchema = z.toJSONSchema(schema);
Copy to clipboardconst schema = z.object({ id: z.number(), name: z.string(), price: z.codec(z.string(), z.number(), { decode: Number, encode: String }), }); const jsonSchema = z.toJSONSchema(schema);
Because of the codec, the input and output types differ (price is a string going in, a number coming out), and so do their JSON schemas.
Standard JSON Schema
Some libraries also implement the Standard JSON Schema interface, which lets a tool generate a JSON schema without specialising for each library:
Copy to clipboardconst jsonSchema = personSchema[ "~standard" ].jsonSchema.input({ target: "draft-2020-12", });
Copy to clipboardconst jsonSchema = personSchema[ "~standard" ].jsonSchema.input({ target: "draft-2020-12" });
Copy to clipboardconst jsonSchema = personSchema["~standard"].jsonSchema.input({ target: "draft-2020-12", });
Copy to clipboardconst jsonSchema = personSchema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
The Standard JSON Schema column shows how each library supports it:
- Native - the library implements it
- Native Opt in - implemented, but it has to be enabled first (e.g.
S.enableStandardJSONSchema()) - Separate package - a separate package implements it (e.g.
@valibot/to-json-schema) - None (blank) - nothing implements it, so only the library's own API is benchmarked
Generated schemas
Every generated schema is checked against the data it describes, but libraries don't agree on what a JSON schema for the same type looks like - each result links to what its library generated.
| Library | Version | /wk | Type | Mean | Compare | ||||
|---|---|---|---|---|---|---|---|---|---|
arktype | Code snippet | Generated JSON schema | 2.2.3 | 1.48M | Input | 413 ns | |||
arktype | Code snippet | Generated JSON schema | 2.2.3 | 1.48M | Output | 429 ns | 1.04x | ||
valibot | Code snippet | Generated JSON schema | 1.5.0 | 13.99M | Input | 598 ns | 1.45x | ||
valibot | Code snippet | Generated JSON schema | 1.5.0 | 13.99M | Output | 601 ns | 1.45x | ||
sury | Code snippet | Generated JSON schema | 11.0.0 | 333.97K | Input | 2 μs | 5.16x | ||
sury | Code snippet | Generated JSON schema | 11.0.0 | 333.97K | Output | 2 μs | 5.27x | ||
effect | Code snippet | Generated JSON schema | 3.22.2 | 24.53M | Input | 2 μs | 5.67x | ||
effect@rc | Code snippet | Generated JSON schema | 4.0.0-rc.112 | 24.53M | Input | 7 μs | 16.97x | ||
zod/mini | Code snippet | Generated JSON schema | 4.6.5 | 209.22M | Output | 7 μs | 17.59x | ||
zod | Code snippet | Generated JSON schema | 4.6.5 | 209.22M | Output | 7 μs | 17.64x | ||
effect | Code snippet | Generated JSON schema | 3.22.2 | 24.53M | Output | 7 μs | 18.14x | ||
zod/mini | Code snippet | Generated JSON schema | 4.6.5 | 209.22M | Input | 9 μs | 21.19x | ||
zod | Code snippet | Generated JSON schema | 4.6.5 | 209.22M | Input | 9 μs | 21.2x | ||