A lightweight JSON Schema validator generator that creates minimal TypeScript code and type definitions
npm install @speria-jp/json-schema-validator-genA lightweight JSON Schema validator generator that creates minimal TypeScript code and type definitions.
- 🚀 Zero runtime dependencies - Generated validators are standalone
- 🔍 Type-safe - Full TypeScript support with generated type definitions
- ⚡ Fast validation - No runtime schema parsing, direct code execution
- 🌐 Universal - Works in Node.js and browsers
- 📋 Detailed errors - Rich error information with path, expected/received values
``bash`
npm install -D @speria-jp/json-schema-validator-genor
yarn add -D @speria-jp/json-schema-validator-genor
pnpm add -D @speria-jp/json-schema-validator-genor
bun add -D @speria-jp/json-schema-validator-gen
Basic usage:
`bashGenerate from root schema (type name derived from file name)
npx @speria-jp/json-schema-validator-gen -s user-schema.json -o validator.ts
If installed locally, you can also use your package manager directly:
`bash
npm
npx json-schema-validator-gen -s schema.json -o validator.tsyarn
yarn json-schema-validator-gen -s schema.json -o validator.tspnpm
pnpm json-schema-validator-gen -s schema.json -o validator.tsbun
bun json-schema-validator-gen -s schema.json -o validator.ts
`Options:
-
-s, --schema - Path to JSON Schema file (required)
- -o, --output - Output path for generated code (required)
- -t, --target - JSON Schema target path (e.g., #/$defs/User). Can be specified multiple times to generate multiple types. Supports custom type names with path=...,name=... format. Defaults to # (root schema)
- -h, --help - Show help message$3
`typescript
import { generate } from '@speria-jp/json-schema-validator-gen';// Generate from root schema (default, type name derived from file name)
const result = await generate({
schemaPath: './user-schema.json',
outputPath: './validator.ts'
});
// Generate from root with custom type name
const result = await generate({
schemaPath: './schema.json',
outputPath: './validator.ts',
targets: ['path=#,name=User']
});
// Generate from specific targets
const results = await generate({
schemaPath: './schema.json',
outputPath: './types.ts',
targets: ['#/$defs/User', '#/$defs/Post']
});
// Generate with custom type names
const results = await generate({
schemaPath: './schema.json',
outputPath: './types.ts',
targets: [
'path=#/$defs/User,name=AppUser',
'path=#/$defs/Post,name=BlogPost'
]
});
`$3
Given a JSON Schema:
`json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "User",
"required": ["id", "name", "email"],
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email",
"pattern": "^[\\w.-]+@[\\w.-]+\\.[a-z]{2,}$"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"role": {
"type": "string",
"enum": ["admin", "user", "guest"]
}
},
"additionalProperties": false
}
`The generator creates:
`typescript
export type User = {
id: number;
name: string;
email: string;
age?: number;
tags?: string[];
role?: "admin" | "user" | "guest";
};// Returns ValidationResult with detailed error information
export function validateUser(value: unknown, options?: ValidationOptions): ValidationResult {
// ... validation logic
}
// Throws an error if validation fails, returns the validated value otherwise
export function unsafeValidateUser(value: unknown): User {
// ... validation logic
}
`Usage:
`typescript
import { validateUser, unsafeValidateUser, type User } from './validator';// Using validateUser - returns ValidationResult
const result = validateUser(data);
if (result.success) {
console.log('Valid user:', result.data);
} else {
console.log('Validation errors:', result.issues);
// Each issue contains: code, path, message, expected, received
}
// Using unsafeValidateUser - throws on invalid input
try {
const user = unsafeValidateUser(data);
console.log('Valid user:', user);
} catch (error) {
console.log('Validation failed:', error.message);
}
// Abort early option - stop on first error
const result = validateUser(data, { abortEarly: true });
`$3
You can generate multiple types from a single JSON Schema file using the
--target option:`bash
Generate User and Post types from $defs (type names derived from path)
npx json-schema-validator-gen -s schema.json -o types.ts \
-t '#/$defs/User' -t '#/$defs/Post'
`Given a JSON Schema with
$defs:`json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$defs": {
"Address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zipCode": { "type": "string" }
},
"required": ["street", "city"]
},
"User": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"email": { "type": "string" },
"address": { "$ref": "#/$defs/Address" }
},
"required": ["id", "name", "email"]
},
"Post": {
"type": "object",
"properties": {
"id": { "type": "string" },
"title": { "type": "string" },
"authorId": { "type": "string" }
},
"required": ["id", "title", "authorId"]
}
}
}
`The generator automatically collects dependencies and creates all necessary types in a single file. Note that
Address is also generated because it's referenced by User, but it's not exported since it wasn't specified in --target:`typescript
// Address type (generated as dependency, not exported)
type Address = {
street: string;
city: string;
zipCode?: string;
};// User type uses type reference instead of inline expansion
export type User = {
id: string;
name: string;
email: string;
address?: Address;
};
export type Post = {
id: string;
title: string;
authorId: string;
};
// Dependency validator (not exported)
function validateAddress(value: unknown): ValidationResult
{ / ... / }// Exported validators for User and Post
export function validateUser(value: unknown): ValidationResult { / ... / }
export function unsafeValidateUser(value: unknown): User { / ... / }
export function validatePost(value: unknown): ValidationResult { / ... / }
export function unsafeValidatePost(value: unknown): Post { / ... / }
`Validation Result
Generated validators return a
ValidationResult discriminated union:`typescript
type ValidationResult =
| { success: true; data: T }
| { success: false; issues: ValidationIssue[] };interface ValidationIssue {
code: ValidationIssueCode;
path: (string | number)[]; // e.g., ["address", "zipCode"] or ["items", 0]
message: string;
expected: string;
received: string;
}
`$3
| Code | Description | Example |
|------|-------------|---------|
|
invalid_type | Value has wrong type | Expected string, received number |
| missing_key | Required property is missing | Missing email property |
| too_small | Value below minimum | Number < minimum, string length < minLength |
| too_big | Value above maximum | Number > maximum, string length > maxLength |
| invalid_string | String doesn't match pattern | Email pattern mismatch |
| invalid_value | Value not in allowed set | Enum value not in list |
| not_integer | Number is not an integer | 25.5 instead of 25 |
| not_unique | Array has duplicate items | ["a", "a"] with uniqueItems: true |
| unrecognized_key | Unknown property | Extra property with additionalProperties: false |Supported JSON Schema Features
- Basic types: string, number, integer, boolean, null, array, object
- Type constraints:
- Numbers: minimum, maximum
- Strings: minLength, maxLength, pattern, format
- Arrays: items validation
- Integers: proper integer validation
- Object validation: required properties, additionalProperties
- Array validation: items schema validation
- Enums and const values: Full enum support
- Union types: Full support for oneOf and anyOf with validation
- References: $ref support for local definitions (#/definitions/ and #/$defs/)
- Optional properties: Proper handling of required vs optional fields
Security Considerations
For general security considerations when working with JSON Schema validation, please refer to the Ajv Security Guidelines. While this tool generates code at build time rather than runtime, many of the same principles apply regarding input validation and schema design.
Development
`bash
Install dependencies
bun installRun development CLI
bun run devBuild the project
bun run buildRun tests
bun testType checking
bun run typecheckLinting
bun run lint
bun run lint:fix
``MIT