How the json-schema-to-zod Utility Works for Type Conversion in Composio
The json-schema-to-zod utility converts JSON Schema definitions into Zod schemas by recursively parsing schema nodes through specialized parsers that map JSON Schema keywords to Zod methods, enabling runtime validation and TypeScript type inference.
The json-schema-to-zod package in the ComposioHQ/composio repository provides a robust bridge between JSON Schema definitions and Zod validation schemas. This TypeScript utility enables developers to generate runtime-validated Zod schemas directly from standard JSON Schema specifications, ensuring type safety across the Composio SDK ecosystem.
Architecture of the json-schema-to-zod Converter
The conversion pipeline operates through three distinct stages: schema normalization, recursive shape building, and parser dispatch.
Entry Point and Schema Normalization
The primary function jsonSchemaToZod in [src/json-schema-to-zod.ts](https://github.com/ComposioHQ/composio/blob/next/ts/packages/json-schema-to-zod/src/json-schema-to-zod.ts) serves as the public API. It accepts a JSON Schema object and optional configuration flags (such as strict mode), resolves $ref pointers, and normalizes composite keywords like allOf, anyOf, and oneOf before delegation.
The Shape Builder Pattern
The jsonSchemaToZodShape function implements the core recursion logic. It traverses the normalized schema tree, inspecting the type keyword and other schema properties to determine which specialized parser should handle the current node. This function returns a Zod-compatible shape object that can be passed to z.object() or other Zod constructors.
Specialized Parser Modules
Individual parsers located in src/parsers/ handle specific JSON Schema types:
- parseString.ts: Maps
format(email, uuid, etc.),minLength,maxLength, andpatternto corresponding Zod string methods like.email(),.uuid(),.min(),.max(), and.regex(). - parseNumber.ts: Translates
minimum,maximum,exclusiveMinimum,exclusiveMaximum, andmultipleOfto Zod number constraints such as.min(),.max(), and.multipleOf(). - parseObject.ts: Constructs Zod object schemas from
propertiesandrequiredarrays, handlingadditionalPropertiesthrough.strict()or.passthrough()modifiers. - parseArray.ts: Converts
items,minItems,maxItems, anduniqueItemsinto Zod array validations using.array(),.min(),.max(), and custom refinements. - parseEnum.ts: Creates
z.enum([...])constructs from JSON Schemaenumarrays. - parseOneOf.ts, parseAnyOf.ts, parseAllOf.ts: Compose Zod unions (
z.union) and intersections (z.intersection) to represent complex type combinations. - parseIfThenElse.ts: Implements conditional schema logic using Zod refinements and unions to handle JSON Schema's
if/then/elseconstructs.
Utility Helpers and Modifiers
The src/utils/ directory contains helper functions that abstract repetitive Zod construction patterns:
- extend-schema.ts: Applies Zod modifiers like
.default(),.describe(), and.optional()based on schema properties such asdefault,description, andnullable. - its.ts: Provides type-guard utilities for safe schema inspection.
- omit.ts: Safely omits keys from object schemas during partial transformations.
Converting JSON Schema to Zod in Practice
The following examples demonstrate practical usage patterns for the utility.
Basic Object Conversion
import { jsonSchemaToZod } from '@composio/json-schema-to-zod';
const userSchema = {
type: 'object',
required: ['id', 'email'],
properties: {
id: { type: 'string', format: 'uuid' },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
additionalProperties: false
};
const zodUser = jsonSchemaToZod(userSchema);
// Generates: z.object({
// id: z.string().uuid(),
// email: z.string().email(),
// age: z.number().int().min(0)
// }).strict()
Accessing Raw Shape Objects
For advanced use cases requiring direct manipulation of the Zod shape before object construction:
import { jsonSchemaToZodShape } from '@composio/json-schema-to-zod';
const shape = jsonSchemaToZodShape(userSchema);
// Returns the raw shape object for custom z.object() wrapping
Strict Mode Validation
To enforce exact object matching without unknown keys:
const strictZod = jsonSchemaToZod(userSchema, { strict: true });
// Equivalent to .strict() modifier on the resulting Zod schema
Provider Integration
The utility integrates throughout the Composio SDK to validate tool parameters:
import { jsonSchemaToZodSchema } from '@composio/core';
// Within provider implementations (OpenAI, LangChain, Claude Agent SDK)
const inputZod = jsonSchemaToZodSchema(tool.inputParameters);
const validatedArgs = inputZod.parse(runtimeArguments);
Key Source Files in the Repository
Summary
- The json-schema-to-zod utility provides a three-stage conversion pipeline: normalization, shape building, and parser dispatch.
- Specialized parsers in
src/parsers/handle specific JSON Schema keywords, translating them to equivalent Zod method chains. - The shape builder pattern allows extraction of raw Zod shapes for custom object construction or provider integration.
- Utility helpers manage cross-cutting concerns like defaults, descriptions, and nullable types through the
extend-schema.tsmodule. - The package is extensively tested in
test/comprehensive-edge-case-tests.tscovering unions, conditionals, and strict mode scenarios.
Frequently Asked Questions
What is the difference between jsonSchemaToZod and jsonSchemaToZodShape?
jsonSchemaToZod returns a complete Zod schema object ready for validation, while jsonSchemaToZodShape returns the raw shape object used internally by z.object(). Use the shape builder when you need to modify the schema structure before final Zod object construction or when integrating with custom Zod utilities.
How does the utility handle JSON Schema references ($ref)?
The entry point in src/json-schema-to-zod.ts normalizes the input schema by resolving $ref pointers and flattening composite keywords (allOf, anyOf, oneOf) before the recursive parsing begins. This ensures the shape builder receives a dereferenced schema tree.
Can the converter handle complex union types and conditional schemas?
Yes. The parseOneOf.ts, parseAnyOf.ts, and parseAllOf.ts parsers generate Zod unions and intersections, while parseIfThenElse.ts implements conditional logic using Zod refinements. The comprehensive test suite in test/comprehensive-edge-case-tests.ts validates these advanced patterns.
Is there a performance difference between strict and non-strict mode?
Strict mode applies the .strict() modifier to object schemas, which adds runtime checks for unknown keys. This incurs minimal overhead during validation but provides stronger type safety. Non-strict mode allows unknown keys to pass through, offering slightly faster validation for objects with variable structures.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →