Skip to content

glideapps/zod-from-json-schema

Repository files navigation

zod-from-json-schema

CI Coverage npm version

A library that creates Zod types from JSON Schema at runtime. This is in contrast to json-schema-to-zod, which generates JavaScript source code.

Installation

npm install zod-from-json-schema

Zod 3 vs 4

Zod 4 is available both as the package version 4, but also as part of the version 3 packages. We support both, as well as Zod 3. Here's which version of this package to use:

Zod zod-from-json-schema
v4 proper latest
v4 via 3.x ^0.4.2
v3 ^0.1.0

Note that the older package for Zod 3 supports a smaller subset of JSON schema than the latest. New features will only be added to the latest.

Usage

This package supports both ESM and CommonJS formats.

ESM (ES Modules)

import { convertJsonSchemaToZod } from 'zod-from-json-schema';

// Define a JSON Schema with advanced features
const jsonSchema = {
  $schema: "https://json-schema.org/draft/2020-12/schema",
  type: "object",
  properties: {
    name: { type: "string", minLength: 2, maxLength: 50 },
    age: { type: "integer", minimum: 0, maximum: 120 },
    email: { type: "string", pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" },
    tags: {
      type: "array",
      items: { type: "string" },
      uniqueItems: true,
      minItems: 1,
      maxItems: 10,
      contains: { enum: ["user", "admin", "guest"] }
    },
    coordinates: {
      type: "array",
      prefixItems: [
        { type: "number", minimum: -90, maximum: 90 },   // latitude
        { type: "number", minimum: -180, maximum: 180 }  // longitude
      ],
      items: false  // No additional items allowed
    },
    score: { type: "number", multipleOf: 0.5, minimum: 0, maximum: 100 }
  },
  required: ["name", "email"],
  additionalProperties: false,
  minProperties: 2,
  maxProperties: 10
};

// Convert JSON Schema to Zod schema
const zodSchema = convertJsonSchemaToZod(jsonSchema);

// Use the Zod schema to validate data
try {
  const validData = zodSchema.parse({
    name: "John Doe",
    email: "john@example.com",
    age: 30,
    tags: ["user", "premium", "admin"],  // Contains required "admin" role
    coordinates: [37.7749, -122.4194],   // San Francisco lat/lng
    score: 87.5  // Multiple of 0.5
  });
  console.log("Valid data:", validData);
} catch (error) {
  console.error("Validation error:", error);
}

CommonJS

const { convertJsonSchemaToZod } = require('zod-from-json-schema');

// Define a JSON Schema
const jsonSchema = {
  $schema: "https://json-schema.org/draft/2020-12/schema",
  type: "object",
  properties: {
    name: { type: "string", minLength: 2, maxLength: 50 },
    age: { type: "integer", minimum: 0, maximum: 120 },
    hobbies: {
      type: "array",
      items: { type: "string" },
      minItems: 1,
      maxItems: 5
    }
  },
  required: ["name"],
  additionalProperties: false,
  minProperties: 1
};

// Convert JSON Schema to Zod schema
const zodSchema = convertJsonSchemaToZod(jsonSchema);

// Use the Zod schema to validate data
try {
  const validData = zodSchema.parse({
    name: "John Doe",
    age: 30,
    hobbies: ["reading", "coding", "gaming"]
  });
  console.log("Valid data:", validData);
} catch (error) {
  console.error("Validation error:", error);
}

API Reference

convertJsonSchemaToZod(schema)

Converts a JSON Schema object to a complete Zod schema.

  • Parameters:
    • schema (Object): A JSON Schema object
  • Returns:
    • A Zod schema that validates according to the JSON Schema

jsonSchemaObjectToZodRawShape(schema)

Extracts the object properties from a JSON Schema object into a Zod raw shape. This is useful when you want to combine the properties with other Zod object configurations.

  • Parameters:
    • schema (Object): A JSON Schema object that should have a properties field
  • Returns:
    • A ZodRawShape object that can be used with z.object()

Example:

import { jsonSchemaObjectToZodRawShape } from 'zod-from-json-schema';
import { z } from 'zod';

const jsonSchema = {
  properties: {
    name: { type: "string" },
    age: { type: "integer" }
  },
  required: ["name"]
};

// Get just the property definitions
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);

// Add custom handling
const customSchema = z.object({
  ...rawShape,
  // Add additional fields not in the JSON Schema
  createdAt: z.date().default(() => new Date())
}).refine(data => data.age > 18, {
  message: "Age must be over 18 to continue"
});

Supported JSON Schema Features

This library provides comprehensive support for JSON Schema Draft 2020-12 features with 100% code coverage and extensive test validation against the official JSON Schema Test Suite.

Basic Types

  • string - Basic string validation
  • number - Numeric values (including integers)
  • integer - Integer-only numeric values
  • boolean - Boolean true/false values
  • null - Null values
  • object - Object validation with property definitions
  • array - Array validation with item constraints

String Validations

  • minLength - Minimum string length (Unicode grapheme-aware)
  • maxLength - Maximum string length (Unicode grapheme-aware)
  • pattern - Regular expression pattern matching

Unicode Support: String length validation correctly counts Unicode grapheme clusters (user-perceived characters) rather than UTF-16 code units, ensuring proper validation of emoji and international text.

Number Validations

  • minimum - Minimum numeric value
  • maximum - Maximum numeric value
  • exclusiveMinimum - Exclusive minimum (greater than)
  • exclusiveMaximum - Exclusive maximum (less than)
  • multipleOf - Multiple validation with floating-point precision handling

Draft-4 Compatibility: The legacy boolean form of exclusiveMinimum/exclusiveMaximum (e.g. { "minimum": 5, "exclusiveMinimum": true }, as used by draft-4 and Swagger 2.0) is also accepted: true makes the sibling minimum/maximum bound exclusive, and false is a no-op.

Array Validations

  • items - Item schema validation (supports schemas, boolean values, and arrays)
  • prefixItems - Tuple-style positional item validation (Draft 2020-12)
  • minItems - Minimum array length
  • maxItems - Maximum array length
  • uniqueItems - Ensures all array items are unique
  • contains - Validates that array contains items matching a schema
  • minContains - Minimum number of items matching the contains schema
  • maxContains - Maximum number of items matching the contains schema

Advanced Array Features:

  • Boolean items schemas (items: false = empty arrays only, items: true = any items allowed)
  • Complex tuple validation with prefixItems and additional items control
  • Sophisticated contains validation with count constraints

Object Validations

  • properties - Property schema definitions
  • required - Required property validation (supports special JavaScript property names)
  • additionalProperties - Controls whether additional properties are allowed
  • patternProperties - Regex-based property validation (partial; see Known Limitations)
  • propertyNames - Validation of property names themselves
  • dependentSchemas - Schema dependencies based on property presence
  • minProperties - Minimum number of object properties
  • maxProperties - Maximum number of object properties
  • dependentRequired - Required properties based on other property presence

Special Property Support: Correctly handles JavaScript reserved property names like constructor and toString — inherited members are not mistaken for property values, and own keys are validated normally. __proto__ is an exception; see Known Limitations.

Schema Composition

  • const - Literal value constraints
  • enum - Enumerated value validation
  • anyOf - Union type validation (basic cases)
  • allOf - Intersection validation (basic cases)
  • oneOf - Exclusive union validation (exactly one schema must match)
  • not - Negation validation
  • if / then / else - Conditional schema application

References and Definitions

  • $ref - Internal references, including JSON pointer fragments (with ~0/~1 and percent-encoding escapes) and references to arbitrary schema locations (e.g. #/properties/foo)
  • $defs / definitions - Schema definitions for reuse
  • $id - Intra-document base URI resolution (nearest-parent bases, relative and absolute URIs, URN and file: bases)
  • $anchor - Location-independent identifiers, scoped to their schema resource
  • $dynamicRef / $dynamicAnchor - Resolved statically, like $ref/$anchor (no dynamic scoping; see Known Limitations)
  • Recursive and mutually recursive references
  • Sibling keywords next to $ref apply conjunctively (Draft 2020-12 semantics)

Remote/external references (documents other than the one being converted) are not yet supported and are ignored; see Known Limitations.

Additional Features

  • title - Schema titles (carried over to Zod schemas)
  • description - Schema descriptions (carried over to Zod schemas)
  • default - Default value annotation, but ignored if it doesn't conform to the schema; a default never satisfies required for a missing property
  • Boolean schemas (true = allow anything, false = allow nothing)
  • Implicit type detection from constraints
  • Comprehensive error messages

Currently Unsupported Features

The following JSON Schema features are not yet implemented:

References and Definitions

  • Remote/external references (referencing documents other than the one being converted)
  • True dynamic scoping for $dynamicRef / $dynamicAnchor (they are resolved statically)

Advanced Object Validation

  • additionalProperties - Fine-grained control over additional properties (basic support exists)
  • unevaluatedProperties - Properties not covered by schema evaluation

Advanced Array Validation

  • unevaluatedItems - Items not covered by schema evaluation
  • Complex prefixItems scenarios with additional item control

Meta-Schema Features

  • Custom vocabularies and meta-schema validation
  • Annotation collection and processing

Known Limitations

Beyond the unsupported keywords above, supported features have some known gaps:

  • __proto__ properties: Zod removes own __proto__ keys from parsed objects to prevent prototype pollution, and this library's validation runs on Zod's parse output. As a result, a __proto__ entry in properties cannot validate its value, and required: ["__proto__"] is only enforced for schemas without an explicit type.
  • Unresolvable references are ignored: A $ref/$dynamicRef that cannot be resolved within the document (remote URIs, unknown anchors, dangling pointers) does not constrain the value at all; the rest of the schema still applies.
  • $dynamicRef is resolved statically: Dynamic scoping is not implemented; $dynamicRef behaves like $ref (and $dynamicAnchor like $anchor), which matches the spec whenever the dynamic anchor is bookended in the same schema resource.
  • Degenerate reference cycles: Reference chains that lead back to themselves without making progress on the data are dropped (treated as unresolvable) when the cycle consists purely of $ref/$dynamicRef edges. Cycles that pass through applicators that don't consume data (e.g. not or allOf) are not detected and will recurse at validation time.
  • Deeply recursive data: Validating recursive schemas against deeply nested data (on the order of a few hundred nesting levels, engine-dependent) can exhaust the JavaScript call stack.
  • unevaluatedProperties is ignored: In particular, discriminated unions whose oneOf variants differ only by unevaluatedProperties: false will not reject inputs that mix properties from different variants. Declaring required properties in each variant makes the variants distinguishable instead.

Standards Compliance

  • JSON Schema Draft 2020-12 - Partial support for core features of the latest JSON Schema standard
  • Official Test Suite - Passes the majority of tests from the official JSON Schema Test Suite (tests for unsupported features are listed in the skip list)

License

MIT

Sponsor

Sponsored by Glide, the platform for custom business software.

About

Create Zod types from JSON Schema at runtime

Resources

License

Stars

34 stars

Watchers

2 watching

Forks

Packages

 
 
 

Contributors