Modern type system for JSON. JSON Type is way a new way to specify JSON schema, it is an alternative and improvement over JSON Schema and JSON Type Definition.
Features of the library:
- JIT compilation for schema validator.
- JIT compilation for JSON (text) serializer.
- JIT compilation for CBOR, MessagePack, and JSON (binary) serializers.
- JIT compilation for safe serialization size estimation.
- Schema export and import.
- Const types.
- Union type discriminator is specified using the JSON Expression language.
- Some discriminators are automatically inferred, when const types are used.
- Custom validation rules can be added using the JSON Expression language.
- Can generate random JSON values that match the schema.
Type builder for JSON-like data structures:
import {t} from '@jsonjoy.com/json-type';
t.String(); // { kind: 'str' }
t.String({const: 'add'}); // { kind: 'str', const: 'add' }
const type = t.Object([
t.Field(
'collection',
t.Object([
t.Field('id', t.String({format: 'ascii', noJsonEscape: true})),
t.Field('ts', t.num, {format: 'u64'}),
t.Field('cid', t.String({format: 'ascii', noJsonEscape: true})),
t.Field('prid', t.String({format: 'ascii', noJsonEscape: true})),
t.Field('slug', t.String({format: 'ascii', noJsonEscape: true})),
t.Field('name', t.str, {isOptional: true}),
t.Field('src', t.str, {isOptional: true}),
t.Field('doc', t.str, {isOptional: true}),
t.Field('authz', t.str, {isOptional: true}),
t.Field('active', t.bool),
]),
),
t.Field(
'block',
t.Object([
t.Field('id', t.String({format: 'ascii', noJsonEscape: true})),
t.Field('ts', t.num, {format: 'u64'}),
t.Field('cid', t.String({format: 'ascii', noJsonEscape: true})),
t.Field('slug', t.String({format: 'ascii', noJsonEscape: true})),
]),
),
]);
JSON Type provides a comprehensive set of node types for modeling JSON-like data structures. Each node type has a kind
property that identifies its type, along with specific properties and constraints.
Represents data of unknown type.
interface AnySchema {
kind: 'any';
validator?: string | string[]; // Custom validation rules
metadata?: Record<string, unknown>; // Custom metadata
}
Example:
s.Any() // { kind: 'any' }
Represents a JSON boolean value.
interface BooleanSchema {
kind: 'bool';
validator?: string | string[]; // Custom validation rules
}
Example:
s.Boolean() // { kind: 'bool' }
Represents a JSON number with optional format and range constraints.
interface NumberSchema {
kind: 'num';
format?: 'i' | 'u' | 'f' | 'i8' | 'i16' | 'i32' | 'i64' | 'u8' | 'u16' | 'u32' | 'u64' | 'f32' | 'f64';
gt?: number; // Greater than (exclusive)
gte?: number; // Greater than or equal to
lt?: number; // Less than (exclusive)
lte?: number; // Less than or equal to
validator?: string | string[];
}
Format options:
i*
- Signed integers (i8, i16, i32, i64)u*
- Unsigned integers (u8, u16, u32, u64)f*
- Floating point (f32, f64)
Examples:
s.Number() // { kind: 'num' }
s.Number({format: 'u32'}) // 32-bit unsigned integer
s.Number({gte: 0, lte: 100}) // Number between 0 and 100
Represents a JSON string with optional format and length constraints.
interface StringSchema {
kind: 'str';
format?: 'ascii' | 'utf8'; // Character encoding format
ascii?: boolean; // @deprecated Use format: 'ascii'
noJsonEscape?: boolean; // Skip JSON escaping for performance
min?: number; // Minimum length
max?: number; // Maximum length
validator?: string | string[];
}
Examples:
s.String() // { kind: 'str' }
s.String({format: 'ascii'}) // ASCII-only string
s.String({min: 1, max: 50}) // String with length constraints
s.String({format: 'ascii', noJsonEscape: true}) // Optimized ASCII string
Represents binary data with an encoded type.
interface BinarySchema {
kind: 'bin';
type: TType; // Type of value encoded in binary
format?: 'json' | 'cbor' | 'msgpack' | 'resp3' | 'ion' | 'bson' | 'ubjson' | 'bencode';
min?: number; // Minimum size in bytes
max?: number; // Maximum size in bytes
validator?: string | string[];
}
Examples:
s.Binary(s.String()) // Binary-encoded string
s.Binary(s.Object(), {format: 'cbor'}) // CBOR-encoded object
Represents a JSON array with elements of a specific type.
interface ArraySchema {
kind: 'arr';
type: TType; // Type of array elements
min?: number; // Minimum number of elements
max?: number; // Maximum number of elements
validator?: string | string[];
}
Examples:
s.Array(s.String()) // Array of strings
s.Array(s.Number(), {min: 1, max: 10}) // Array with 1-10 numbers
Represents a fixed-length array with specific types for each position.
interface TupleSchema {
kind: 'tup';
types: TType[]; // Types for each position
validator?: string | string[];
}
Example:
s.Tuple(s.String(), s.Number(), s.Boolean()) // [string, number, boolean]
Represents a JSON object with defined fields.
interface ObjectSchema {
kind: 'obj';
fields: ObjectFieldSchema[]; // Defined object fields
unknownFields?: boolean; // @deprecated Allow undefined fields
encodeUnknownFields?: boolean; // Include unknown fields in output
validator?: string | string[];
}
Examples:
s.Object([
s.prop('name', s.String()),
s.propOpt('age', s.Number()) // Optional field
])
Represents a single field in an object.
interface ObjectFieldSchema {
kind: 'field';
key: string; // Field name
type: TType; // Field value type
optional?: boolean; // Whether field is optional
}
Examples:
s.prop('id', s.String()) // Required field
s.propOpt('description', s.String()) // Optional field
Represents an object treated as a map with string keys and uniform value types.
interface MapSchema {
kind: 'map';
type: TType; // Type of all values
validator?: string | string[];
}
Example:
s.Map(s.Number()) // Object with number values
Represents a constant value.
interface ConstSchema {
kind: 'const';
value: any; // The constant value
validator?: string | string[];
}
Examples:
s.Const('hello' as const) // Constant string
s.Const(42 as const) // Constant number
s.Const(null) // Null constant
References another type by ID.
interface RefSchema {
kind: 'ref';
ref: string; // ID of referenced type
}
Example:
s.Ref('UserType') // Reference to type with ID 'UserType'
Represents a union type (one of multiple possible types).
interface OrSchema {
kind: 'or';
types: TType[]; // Possible types
discriminator: Expr; // Expression to determine type
}
Example:
s.Or(s.String(), s.Number()) // String or number
Represents a function type with request and response.
interface FunctionSchema {
kind: 'fn';
req: TType; // Request type
res: TType; // Response type
}
Example:
s.Function(s.String(), s.Number()) // Function: string -> number
Represents a streaming function type.
interface FunctionStreamingSchema {
kind: 'fn$';
req: TType; // Request stream type
res: TType; // Response stream type
}
Example:
s.Function$(s.String(), s.Number()) // Streaming function
All node types extend the base TType
interface with these common properties:
interface TType {
kind: string; // Node type identifier
// Display properties
title?: string; // Human-readable title
intro?: string; // Short description
description?: string; // Long description (may include Markdown)
// Metadata
id?: string; // Unique identifier
meta?: Record<string, unknown>; // Custom metadata
examples?: TExample[]; // Usage examples
// Deprecation
deprecated?: {
description?: string; // Deprecation reason and alternative
};
}
Many types support custom validation through the validator
property:
// Single validator
{ validator: 'email' }
// Multiple validators
{ validator: ['required', 'email'] }
Validation rules are applied using the JSON Expression language for flexible custom constraints.