molt-json - Type-Preserving JSON Transformer โ
The world's fastest JSON transformer with dirty input support, type preservation, and streaming capabilities.
Overview โ
@sylphx/molt-json is an ultra-fast JSON parser and serializer that handles real-world, malformed JSON and preserves JavaScript types through serialization cycles.
Key Features โ
- ๐ 380x faster than dirty-json at parsing malformed JSON
- ๐ฅ 2.3x faster than superjson at type-preserving serialization
- ๐งน Dirty JSON support - Unquoted keys, comments, trailing commas
- ๐ฏ Type preservation - Date, BigInt, Map, Set, RegExp, Uint8Array
- ๐ Streaming API - Process large files without memory overhead
- โ Schema validation - Compatible with Zod, JSON Schema
- ๐ก๏ธ Zero dependencies - Pure TypeScript implementation
- ๐ฆ Battle-tested - 119+ test cases
Installation โ
bash
npm install @sylphx/molt-jsonQuick Start โ
Parse Dirty JSON โ
typescript
import { molt } from '@sylphx/molt-json'
const data = molt(`{
user: 'alice', // โ
Unquoted keys
email: 'alice@test.com', // โ
Single quotes
age: 30, // โ
Trailing comma
active: true,
}`)
console.log(data)
// Output: { user: 'alice', email: 'alice@test.com', age: 30, active: true }Type Preservation โ
typescript
import { molt, stringify } from '@sylphx/molt-json'
const original = {
created: new Date('2024-01-01'),
id: 123456789012345678901n, // BigInt
tags: new Set(['a', 'b']),
config: new Map([['key', 'value']]),
pattern: /^test$/i,
data: new Uint8Array([1, 2, 3])
}
// Serialize with type metadata
const json = stringify(original)
// Deserialize and restore types
const restored = molt(json)
console.log(restored.created instanceof Date) // true
console.log(restored.id === 123456789012345678901n) // true
console.log(restored.tags instanceof Set) // true
console.log(restored.config instanceof Map) // true
console.log(restored.pattern instanceof RegExp) // true
console.log(restored.data instanceof Uint8Array) // truePerformance โ
Benchmarks on 1.5KB malformed JSON with complex types:
| Library | Operations/sec | vs molt-json |
|---|---|---|
| molt-json | 170,000 | 1x (baseline) |
| superjson | 119,000 | 0.7x |
| dirty-json | 448 | 0.003x (380x slower) |
Why So Fast? โ
- State machine parser - No regex = no ReDoS vulnerability
- Zero-copy strings - Minimal memory allocation
- Optimized type detection - Priority-based type registry
- Minimal overhead - Small metadata footprint
Supported Dirty JSON Features โ
Unquoted Keys โ
typescript
molt(`{
name: 'Alice',
age: 30,
email: 'alice@test.com'
}`)Single Quotes โ
typescript
molt(`{
message: 'Hello, World!'
}`)JavaScript Comments โ
typescript
molt(`{
// This is a comment
name: 'Alice', /* inline comment */
age: 30
}`)Trailing Commas โ
typescript
molt(`{
items: [1, 2, 3,],
tags: ['a', 'b',],
}`)Mixed Formats โ
typescript
molt(`{
// Complex object
user: { name: 'Alice', age: 30, },
settings: new Map([['theme', 'dark']]),
created: new Date(),
}`)Type Preservation Details โ
Supported Types โ
Date- JavaScript Date objectsBigInt- Arbitrary precision integersMap- Key-value collectionsSet- Unique value collectionsRegExp- Regular expressionsUint8Array- Byte arraysError- Error objects with stack traces- Custom classes - Via type registry
How It Works โ
The stringify function adds metadata about types:
typescript
const json = stringify({
date: new Date('2024-01-01'),
bigint: 123n
})
// Produces something like:
// {
// "date": {"__type": "Date", "value": "2024-01-01T00:00:00.000Z"},
// "bigint": {"__type": "BigInt", "value": "123"}
// }Then molt (or parse) restores the original types:
typescript
const restored = molt(json)
restored.date instanceof Date // true
typeof restored.bigint === 'bigint' // trueAPI Reference โ
molt(input, options?) โ
Parse dirty JSON or type-preserved JSON.
typescript
function molt<T = any>(
input: string,
options?: ParseOptions
): TOptions:
strict?: boolean- Throw on invalid JSON (default: false)allowComments?: boolean- Allow JS comments (default: true)allowTrailingCommas?: boolean- Allow trailing commas (default: true)allowUnquotedKeys?: boolean- Allow unquoted keys (default: true)
stringify(value, options?) โ
Stringify with type preservation.
typescript
function stringify(
value: any,
options?: StringifyOptions
): stringOptions:
pretty?: boolean- Pretty-print output (default: false)indent?: number- Indent size (default: 2)preserveTypes?: boolean- Preserve types (default: true)
parse(input, options?) โ
Parse JSON without dirty input support (pure JSON).
typescript
function parse<T = any>(
input: string,
options?: ParseOptions
): TSchema Validation โ
Molt integrates seamlessly with validation libraries:
Zod โ
typescript
import { molt } from '@sylphx/molt-json'
import { z } from 'zod'
const UserSchema = z.object({
name: z.string(),
age: z.number().positive(),
email: z.string().email()
})
const data = molt('{ name: "Alice", age: 30, email: "alice@test.com" }')
const validated = UserSchema.parse(data)JSON Schema โ
typescript
import { molt } from '@sylphx/molt-json'
import Ajv from 'ajv'
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' }
},
required: ['name', 'age']
}
const ajv = new Ajv()
const validate = ajv.compile(schema)
const data = molt('{ name: "Alice", age: 30 }')
if (validate(data)) {
console.log('Valid!')
} else {
console.log('Invalid:', validate.errors)
}Error Handling โ
typescript
import { molt } from '@sylphx/molt-json'
try {
const data = molt('{ invalid ]')
} catch (error) {
console.error('Parse error at position:', error.position)
console.error('Message:', error.message)
}Error objects include:
message- Error descriptionposition- Character position in inputline- Line numbercolumn- Column number
Streaming (Advanced) โ
For very large JSON files, use the streaming API:
typescript
import { createReadStream } from 'fs'
import { createMoltStream } from '@sylphx/molt-json'
const stream = createReadStream('large.json')
const moltStream = createMoltStream()
stream.pipe(moltStream)
moltStream.on('data', (obj) => {
console.log('Parsed object:', obj)
})
moltStream.on('error', (err) => {
console.error('Stream error:', err)
})Comparison with Alternatives โ
vs Native JSON โ
typescript
// โ Native fails on dirty JSON
JSON.parse('{ key: "value" }') // SyntaxError
// โ
molt handles it
molt('{ key: "value" }') // Works!vs dirty-json โ
typescript
// molt is 380x faster
molt(dirtyJson) // 170,000 ops/sec
dirtyJson.parse(dirtyJson) // 448 ops/secvs superjson โ
typescript
// molt is 2.3x faster at serialization
molt.stringify(data) // 610,000 ops/sec
superjson.stringify(data) // 250,000 ops/secBest Practices โ
- Use
stringifyfor round-trip serialization - Preserves types - Use
moltfor parsing dirty JSON - Handles real-world data - Validate after parsing - Use Zod or JSON Schema
- Handle errors - JSON can be invalid
- Consider streaming - For files larger than 100MB
Resources โ
Next: Explore other packages or check the Benchmarks