@hyperfrontend/json-utilsView on npm →API Reference →

@hyperfrontend/json-utils

Zero-dependency JSON Schema Draft v4 validation and schema generation utilities.

What is @hyperfrontend/json-utils?

@hyperfrontend/json-utils provides lightweight utilities for validating JSON data against JSON Schema Draft v4 specifications and generating schemas from JavaScript values via a functional-programming-first implementation.

The library provides two core capabilities: validation (checking if data conforms to a schema) and generation (creating a schema from sample data). Both functions use pure functional design with no side effects, making them predictable and easy to test.

Key Features

  • Full JSON Schema Draft v4 Support - Validates type, properties, required, items, enum, pattern, minimum/maximum, allOf/anyOf/oneOf/not, $ref, format, and more
  • Schema Generation - Create schemas from sample data with configurable array handling modes
  • Reusable Validators - Create validator functions once, reuse them efficiently
  • Detailed Error Messages - Get precise error paths, messages, and codes for failed validations
  • Zero External Dependencies - Self-contained implementation with no third-party runtime dependencies
  • Isomorphic Design - Works identically in Node.js and browser environments

What This Library Does NOT Support

  • JSON Schema Draft 6, 7, 2019-09, or 2020-12 - Only Draft v4 is implemented
  • External $ref Resolution - Only internal references (#/definitions/...) are supported; no HTTP or file-based schema loading
  • const, contains, propertyNames, if/then/else - These are Draft 6+ features
  • Custom Format Validators - Built-in formats only (email, uri, date-time, etc.)

If you need full JSON Schema support across multiple draft versions, consider Ajv. This library is intentionally scoped for Draft v4 use cases where a lightweight, zero-dependency solution is preferred.

Architecture Highlights

The library uses a functional composition approach with pure validation functions. The core validate function recursively traverses schemas and data, delegating to specialized validators for each JSON Schema keyword. Schema references ($ref) are resolved through a context object that tracks definitions, enabling circular reference handling. Error collection uses accumulation rather than early termination, providing complete validation feedback in a single pass.

Why Use @hyperfrontend/json-utils?

Validate User-Provided Schemas

When your application accepts user-defined JSON Schema (like contract definitions or API specifications), you need reliable validation. This library validates both the data and can verify that schemas themselves are valid Draft v4 documents using the meta-schema.

Generate Schemas from Sample Data

Instead of manually writing schemas for data structures, generate them from representative samples. Useful for testing, documentation generation, and bootstrap schema creation.

Functional Programming Approach

All functions are pure with no side effects. Create validator functions with createValidator() and reuse them without worrying about shared state. Validation contexts are immutable and composable.

Installation

npm install @hyperfrontend/json-utils

Quick Start

Validate Data Against a Schema

import { validate } from '@hyperfrontend/json-utils'
import type { Schema } from '@hyperfrontend/json-utils'

const schema: Schema = {
  type: 'object',
  properties: {
    name: { type: 'string', minLength: 1 },
    age: { type: 'integer', minimum: 0 },
    email: { type: 'string', format: 'email' },
  },
  required: ['name', 'email'],
}

const result = validate({ name: 'Alice', email: 'alice@example.com' }, schema)
console.log(result.valid) // true

const invalid = validate({ name: '', age: -5 }, schema)
console.log(invalid.valid) // false
console.log(invalid.errors)
// [
//   { message: 'Missing required property: email', path: '/', code: 'required' },
//   { message: 'String must be at least 1 characters, got 0', path: '/name', code: 'minLength' },
//   { message: 'Number must be at least 0, got -5', path: '/age', code: 'minimum' }
// ]

Create Reusable Validators

import { createValidator } from '@hyperfrontend/json-utils'

const validateUser = createValidator({
  type: 'object',
  properties: {
    id: { type: 'integer' },
    username: { type: 'string', pattern: '^[a-z0-9_]+$' },
  },
  required: ['id', 'username'],
})

// Reuse without re-parsing schema
validateUser({ id: 1, username: 'alice' }) // { valid: true, errors: [] }
validateUser({ id: 'bad' }) // { valid: false, errors: [...] }

Generate Schemas from Data

import { toJsonSchema } from '@hyperfrontend/json-utils'

const data = {
  users: [
    { name: 'Alice', active: true },
    { name: 'Bob', active: false },
  ],
  metadata: { version: '1.0' },
}

const schema = toJsonSchema(data)
// {
//   type: 'object',
//   properties: {
//     users: {
//       type: 'array',
//       items: {
//         type: 'object',
//         properties: {
//           name: { type: 'string' },
//           active: { type: 'boolean' }
//         },
//         required: ['name', 'active']
//       }
//     },
//     metadata: {
//       type: 'object',
//       properties: { version: { type: 'string' } },
//       required: ['version']
//     }
//   },
//   required: ['users', 'metadata']
// }

Use $ref for Reusable Definitions

import { validate } from '@hyperfrontend/json-utils'

const schema = {
  definitions: {
    address: {
      type: 'object',
      properties: {
        street: { type: 'string' },
        city: { type: 'string' },
      },
      required: ['street', 'city'],
    },
  },
  type: 'object',
  properties: {
    home: { $ref: '#/definitions/address' },
    work: { $ref: '#/definitions/address' },
  },
}

validate(
  {
    home: { street: '123 Main', city: 'Boston' },
    work: { street: '456 Oak', city: 'Cambridge' },
  },
  schema
) // { valid: true, errors: [] }

API Overview

Validation

  • validate(instance, schema, options?): ValidationResult - Validate a value against a JSON Schema
  • createValidator(schema, options?): (data) => ValidationResult - Create a reusable validator function

Generation

  • toJsonSchema(value, options?): Schema - Generate a JSON Schema from a JavaScript value

Utilities

  • getJsonType(value): JsonType - Get the JSON Schema type of a JavaScript value
  • isEqual(a, b): boolean - Deep equality comparison for JSON values
  • checkPatternSafety(pattern): PatternSafetyResult - Check if a regex pattern may cause ReDoS

Types

  • Schema - TypeScript interface representing JSON Schema Draft v4
  • JsonType - 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null'
  • ValidationResult - { valid: boolean, errors: ValidationError[] }
  • ValidationError - { message: string, path: string, code?: string, instance?: unknown, params?: object }
  • ValidateOptions - Validation configuration (see below)
  • GenerateOptions - { arrays?: { mode: 'all' | 'first' | 'uniform' }, includeRequired?: boolean }
  • PatternSafetyChecker - Custom function for ReDoS pattern detection
  • PatternSafetyResult - { safe: boolean, reason?: string }

ValidateOptions

Option Type Default Description
collectAllErrors boolean true When false, stops at first error
strictPatterns boolean false Report errors for invalid regex patterns (syntax errors)
safePatterns boolean | PatternSafetyChecker false Enable ReDoS protection (see Security section)

Security: ReDoS Protection

JSON Schema's pattern and patternProperties keywords accept arbitrary regex patterns. Malicious or poorly-crafted patterns can cause ReDoS (Regular Expression Denial of Service) attacks with exponential backtracking.

Built-in Heuristics

Enable built-in ReDoS detection with safePatterns: true:

import { validate } from '@hyperfrontend/json-utils'

const schema = { type: 'string', pattern: '(a+)+' } // Known ReDoS pattern

const result = validate('aaa', schema, { safePatterns: true })
// result.valid = false
// result.errors[0].message = 'Unsafe regex pattern: Nested quantifiers detected...'

The built-in checker detects common dangerous patterns:

  • Nested quantifiers: (a+)+, (a*)*, ([a-z]+)+
  • Overlapping alternations: (a|a)+
  • Multiple unbounded wildcards: .*.*
  • Extremely large quantifier bounds: a{1,100000}

Custom Checker (Recommended for Production)

For comprehensive protection, provide a custom checker using safe-regex2:

import { validate, type PatternSafetyChecker } from '@hyperfrontend/json-utils'
import safeRegex from 'safe-regex2'

const checker: PatternSafetyChecker = (pattern) => ({
  safe: safeRegex(pattern),
  reason: 'Pattern may cause catastrophic backtracking',
})

validate(data, schema, { safePatterns: checker })

Exported Utilities

import { checkPatternSafety } from '@hyperfrontend/json-utils'

// Use built-in heuristics directly
const result = checkPatternSafety('(a+)+')
// { safe: false, reason: 'Nested quantifiers detected...' }

Supported Keywords

Category Keywords
Type type
Object properties, required, additionalProperties, patternProperties, minProperties, maxProperties, dependencies
Array items, additionalItems, minItems, maxItems, uniqueItems
String minLength, maxLength, pattern, format
Number minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf
Composition allOf, anyOf, oneOf, not
Reference $ref, definitions
Enum enum
Format email, uri, uri-reference, date-time, date, time, hostname, ipv4, ipv6, uuid, regex, json-pointer

Compatibility

Platform Support
Browser
Node.js
Web Workers
Deno, Bun, Cloudflare Workers

Output Formats

Format File Tree-Shakeable
ESM index.esm.js
CJS index.cjs.js
IIFE bundle/index.iife.min.js
UMD bundle/index.umd.min.js

CDN Usage

<!-- unpkg -->
<script src="https://unpkg.com/@hyperfrontend/json-utils"></script>

<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@hyperfrontend/json-utils"></script>

<script>
  const { validate, toJsonSchema } = HyperfrontendJsonUtils
</script>

Global variable: HyperfrontendJsonUtils

Dependencies

None — zero external dependencies.

Part of hyperfrontend

This library is part of the hyperfrontend monorepo.

📖 Full documentation

License

MIT

API Reference§

Filter:

ƒFunctions

§function

checkPatternSafety(pattern: string): PatternSafetyResult

Built-in heuristic pattern safety checker. Detects common ReDoS-vulnerable patterns without external dependencies.
This is a best-effort implementation that catches obvious cases:
  • Nested quantifiers: (a+)+, (a), (a+), etc.
  • Overlapping alternations with repetition: (a|a)+
  • Quantified groups followed by overlapping content: (.+)x
For comprehensive protection, use a dedicated library like safe-regex2.

Parameters

NameTypeDescription
§pattern
string
The regex pattern string to check

Returns

PatternSafetyResult
Result indicating if the pattern is safe

Example

Checking pattern safety

checkPatternSafety('^[a-z]+$')  // => { safe: true }
checkPatternSafety('(a+)+')     // => { safe: false, reason: 'Nested quantifiers...' }
checkPatternSafety('.*.*')      // => { safe: false, reason: 'Multiple unbounded wildcards...' }
§function

createValidator(schema: Schema, options?: ValidateOptions): (data: unknown) => ValidationResult

Creates a reusable validator function from a JSON Schema.

Parameters

NameTypeDescription
§schema
Schema
JSON Schema to validate against
§options?
ValidateOptions
Validation options

Returns

(data: unknown) => ValidationResult
A function that validates data against the schema

Example

Creating reusable validator

const schema = {
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'integer', minimum: 0 }
  },
  required: ['name']
}

const validateUser = createValidator(schema)
const result = validateUser({ name: 'Alice', age: 30 })
console.log(result.valid) // true
§function

getJsonType(value: unknown): JsonType

Gets the JSON Schema type of a JavaScript value.

Parameters

NameTypeDescription
§value
unknown
The value to determine the type of

Returns

JsonType
The JSON Schema type

Example

Detecting JSON types

getJsonType('hello')    // => 'string'
getJsonType(42)         // => 'integer'
getJsonType(3.14)       // => 'number'
getJsonType(true)       // => 'boolean'
getJsonType(null)       // => 'null'
getJsonType([1, 2, 3])  // => 'array'
getJsonType({ key: 1 }) // => 'object'
§function

isEqual(a: unknown, b: unknown): boolean

Performs deep equality check for JSON values.
Used for enum validation and uniqueItems validation.

Parameters

NameTypeDescription
unknown
First value to compare
unknown
Second value to compare

Returns

boolean
true if values are deeply equal, false otherwise

Example

Comparing values for equality

isEqual({ name: 'Alice' }, { name: 'Alice' }) // => true
isEqual([1, 2, 3], [1, 2, 3])                 // => true
isEqual({ a: 1 }, { a: 2 })                   // => false
isEqual([1, 2], [2, 1])                       // => false (order matters)
§function

toJsonSchema(value: unknown, options?: GenerateOptions): Schema

Generates a JSON Schema from a JavaScript value.

Parameters

NameTypeDescription
§value
unknown
The value to generate a schema from
§options?
GenerateOptions
Generation options

Returns

Schema
A JSON Schema describing the value

Example

Generating schema from data

const data = {
  name: 'Alice',
  age: 30,
  tags: ['developer', 'typescript']
}

const schema = toJsonSchema(data)
// {
//   type: 'object',
//   properties: {
//     name: { type: 'string' },
//     age: { type: 'integer' },
//     tags: { type: 'array', items: { type: 'string' } }
//   },
//   required: ['name', 'age', 'tags']
// }
§function

validate(instance: unknown, schema: Schema, options?: ValidateOptions): ValidationResult

Validates a value against a JSON Schema.

Parameters

NameTypeDescription
§instance
unknown
The value to validate
§schema
Schema
The JSON Schema to validate against
§options?
ValidateOptions
Validation options

Returns

ValidationResult
Validation result with valid flag and any errors

Example

Basic validation

const schema = { type: 'string', minLength: 1 }
const result = validate('hello', schema)
console.log(result.valid) // true

Interfaces

§interface

GenerateOptions

Options for schema generation.

Properties

§additionalProperties?:boolean
Whether to allow additional properties (default: true)
§arrays?:{ mode: "first" | "all" | "uniform" }
Array handling mode
§includeRequired?:boolean
Whether to include required fields (default: true)
§interface

PatternSafetyResult

Result of a pattern safety check.

Properties

§reason?:string
Reason if unsafe (for error reporting)
§safe:boolean
Whether the pattern is considered safe
§interface

Schema

JSON Schema Draft v4 type definition. Represents the structure of a JSON Schema document.

Properties

§$ref?:string
Reference to another schema
§$schema?:string
Draft version
§additionalItems?:boolean | Schema
Schema for additional items beyond tuple
§additionalProperties?:boolean | Schema
Schema for additional properties, or false to disallow
§allOf?:Schema[]
All schemas must match
§anyOf?:Schema[]
At least one schema must match
§default?:unknown
Default value
§definitions?:Record<string, Schema>
Reusable schema definitions
§dependencies?:Record<string, string[] | Schema>
Property dependencies
§description?:string
Human-readable description
§enum?:unknown[]
Enum constraint - value must be one of these
§exclusiveMaximum?:boolean
Whether maximum is exclusive (Draft v4 style)
§exclusiveMinimum?:boolean
Whether minimum is exclusive (Draft v4 style)
§format?:string
String format (e.g., 'email', 'uri', 'date-time')
§id?:string
Schema identifier (Draft v4 uses 'id', not '$id')
§items?:Schema | Schema[]
Schema for array items (single or tuple)
§maximum?:number
Maximum value
§maxItems?:number
Maximum array length
§maxLength?:number
Maximum string length
§maxProperties?:number
Maximum number of properties
§minimum?:number
Minimum value
§minItems?:number
Minimum array length
§minLength?:number
Minimum string length
§minProperties?:number
Minimum number of properties
§multipleOf?:number
Value must be a multiple of this
§not?:Schema
Schema must NOT match
§oneOf?:Schema[]
Exactly one schema must match
§pattern?:string
Regex pattern the string must match
§patternProperties?:Record<string, Schema>
Pattern-based property schemas
§properties?:Record<string, Schema>
Property schemas
§required?:string[]
Required property names
§title?:string
Human-readable title
§type?:JsonType | JsonType[]
Type constraint
§uniqueItems?:boolean
Whether array items must be unique
§interface

ValidateOptions

Options for validation operations.

Properties

§collectAllErrors?:boolean
Whether to collect all errors or stop at first (default: true)
§safePatterns?:boolean | PatternSafetyChecker
Whether to check patterns for ReDoS vulnerabilities (default: false). When true, uses built-in heuristics to detect common dangerous patterns. When a function is provided, uses that function for safety checking.
Built-in heuristics catch obvious cases like nested quantifiers. For comprehensive protection, provide a custom checker using safe-regex2.
§strictPatterns?:boolean
Whether to report errors for invalid regex patterns (default: false)
§interface

ValidationError

Individual validation error.

Properties

§code?:string
Optional error code for programmatic handling
§instance?:unknown
The value that failed validation
§message:string
Human-readable error message
§params?:Record<string, unknown>
Additional error parameters
§path:string
JSON Pointer path to the failing property (e.g., '/foo/bar/0')
§interface

ValidationResult

Result of a validation operation.

Properties

§errors:ValidationError[]
Array of validation errors (empty if valid)
§valid:boolean
Whether validation passed

Types

§type

JsonType

JSON Schema type values.
type JsonType = "string" | "number" | "integer" | "boolean" | "array" | "object" | "null"
§type

PatternSafetyChecker

Function type for custom pattern safety checkers. Users can provide their own implementation (e.g., using safe-regex2).
type PatternSafetyChecker = (pattern: string) => PatternSafetyResult

Related