Skip to content

JSON Type implementation. Fast JSON data type schema validation with JIT compilation.

Notifications You must be signed in to change notification settings

jsonjoy-com/json-type

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

50 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JSON Type

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.

Usage

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})),
    ]),
  ),
]);

Node Types

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.

Core Types

AnySchema (any)

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' }

BooleanSchema (bool)

Represents a JSON boolean value.

interface BooleanSchema {
  kind: 'bool';
  validator?: string | string[];  // Custom validation rules
}

Example:

s.Boolean()  // { kind: 'bool' }

NumberSchema (num)

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

StringSchema (str)

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

BinarySchema (bin)

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

Composite Types

ArraySchema (arr)

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

TupleSchema (tup)

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]

ObjectSchema (obj)

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
])

ObjectFieldSchema (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  

MapSchema (map)

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

Advanced Types

ConstSchema (const)

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

RefSchema (ref)

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'

OrSchema (or)

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

FunctionSchema (fn)

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

FunctionStreamingSchema (fn$)

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

Common Properties

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
  };
}

Validation

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.

About

JSON Type implementation. Fast JSON data type schema validation with JIT compilation.

Resources

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published