json-alexander
v0.1.14
Published
Serenity Now! Forgiving JSON parser
Readme
json-alexander
Forgiving JSON parsing for CLI arguments, config snippets, and other places where humans type almost-JSON.
npm install json-alexanderconst { parseJSON } = require('json-alexander')
parseJSON('{ hello: there, cool: true, list: [one, two, 3] }')
// => { hello: 'there', cool: true, list: ['one', 'two', 3] }TL;DR
The problem: strict JSON.parse is correct, but it is hostile to command-line and handwritten input. A missing quote, single quote, trailing comma, or bare object key turns the whole payload into an exception.
The solution: json-alexander tries strict JSON first, then applies a small forgiving parser and repair path for common human-authored JSON mistakes.
| You have | JSON.parse | parseJSON |
| --- | --- | --- |
| { foo: bar } | Throws | { foo: 'bar' } |
| {'foo': 'bar',} | Throws | { foo: 'bar' } |
| [one, two, 3] | Throws | ['one', 'two', 3] |
| {"valid": true} | Works | Works |
| null, 0, false, "" | Works | Works |
Quick Example
const { parseJSON, safeParse } = require('json-alexander')
parseJSON('{"valid": "json"}')
// => { valid: 'json' }
parseJSON("{'single': 'quotes'}")
// => { single: 'quotes' }
parseJSON('{ missing: quotes }')
// => { missing: 'quotes' }
parseJSON('{ trailing: "comma", }')
// => { trailing: 'comma' }
parseJSON('[one, [two, 3], { four: [five, { six: true }] }]')
// => ['one', ['two', 3], { four: ['five', { six: true }] }]
safeParse("{'not': 'strict json'}")
// => undefinedWhen To Use It
| Good fit | Poor fit |
| --- | --- |
| CLI flags like --data '{ foo: bar }' | Untrusted server request bodies |
| Internal tools and developer ergonomics | Security boundaries |
| Config snippets authored by humans | Full JSON5 compatibility |
| Best-effort parsing before a helpful error | Validation of data shape or schema |
This package parses values. It does not validate that the resulting object has the shape your application expects.
Installation
npm install json-alexanderpnpm add json-alexanderyarn add json-alexanderAPI
parseJSON(input, defaultValue?)
Forgiving parser. It returns parsed JavaScript values when possible and throws when the input cannot be parsed or repaired.
const { parseJSON } = require('json-alexander')
parseJSON('false')
// => false
parseJSON('"false"')
// => 'false'
parseJSON('0')
// => 0
parseJSON('null')
// => null
parseJSON('')
// => ''
parseJSON('', [])
// => []parseJSON accepts native JavaScript values too:
parseJSON({ already: 'an object' })
// => { already: 'an object' }
parseJSON(['already', 'an array'])
// => ['already', 'an array']safeParse(input, defaultValue?)
Strict parser. It uses JSON.parse, passes native objects/arrays through, and returns defaultValue when strict parsing fails.
const { safeParse } = require('json-alexander')
safeParse('{"valid": true}')
// => { valid: true }
safeParse("{'not': 'strict'}")
// => undefined
safeParse("{'not': 'strict'}", {})
// => {}
safeParse({ already: 'parsed' })
// => { already: 'parsed' }Use safeParse when you want strict JSON behavior without throwing on invalid input.
Supported Loose Syntax
| Input | Output |
| --- | --- |
| { cool: beans } | { cool: 'beans' } |
| { cool: 'beans' } | { cool: 'beans' } |
| { cool: true, nope: false } | { cool: true, nope: false } |
| { count: 3, price: 1.25 } | { count: 3, price: 1.25 } |
| { nil: null } | { nil: null } |
| [one, two, 3] | ['one', 'two', 3] |
| { a: [1, 2,], b: { c: 3, }, } | { a: [1, 2], b: { c: 3 } } |
| { url: https://example.com?a=1&b=2 } | { url: 'https://example.com?a=1&b=2' } |
Quoted values stay strings:
parseJSON('{ quotedNull: "null", quotedFalse: "false", quotedZero: "0" }')
// => { quotedNull: 'null', quotedFalse: 'false', quotedZero: '0' }Design Notes
Strict JSON wins first. Valid JSON is returned directly from
JSON.parse, including falsy root values likenull,0,false, and"".Loose parsing is best-effort. The parser targets common CLI/config mistakes, not every JavaScript object literal feature.
Quoted content is protected. Delimiters inside quoted strings, such as commas, braces, and comment-like text, are preserved as string content.
Security-sensitive paths should stay strict. Use
safeParseor nativeJSON.parsefor untrusted server input.
Architecture
input
|
|-- null / undefined / empty string handling
|
|-- strict JSON.parse
| |
| '-- success: return exact JSON value
|
|-- loose container parser
| |
| '-- handles bare keys, bare values, nested arrays/objects, trailing commas
|
|-- legacy repair passes
| |
| '-- quote fixes, comma cleanup, bracket balancing
|
'-- throw if no path can produce a valueSecurity And Performance
parseJSON is intentionally forgiving, which means it performs more work than JSON.parse. It is designed for convenience in bounded inputs such as CLI arguments and config snippets.
For security-sensitive or long-running server code:
const { safeParse } = require('json-alexander')
const value = safeParse(input, null)The repository includes an adversarial timing check for the regex and parser paths:
npm run verifyThe test suite covers strict JSON values, loose objects, loose arrays, nested containers, trailing commas, quoted delimiters, URL-like values, and safe parsing behavior:
npm testComparison
| Package | Primary goal | Forgiving repairs | Safe strict mode | Notes |
| --- | --- | --- | --- | --- |
| json-alexander | Human-friendly CLI/config parsing | Yes | Yes, via safeParse | Small CommonJS library |
| JSON.parse | Standards-compliant JSON | No | Yes | Fastest and strictest |
| json5 | JSON5 syntax support | Yes, by spec | No separate safe helper | Better if you want JSON5 as a format |
| dirty-json | Parse malformed JSON-like text | Yes | No separate safe helper | Broader dirty JSON parser |
Troubleshooting
parseJSON throws Unable to parse JSON
The input is outside the repair grammar. If the value comes from a user or network request, prefer rejecting it or using safeParse(input, fallback).
safeParse(input, {})
// => parsed object or {}A value became a string
Bare words are treated as strings.
parseJSON('{ mode: production }')
// => { mode: 'production' }Use valid JSON when you need exact types beyond booleans, null, and numbers.
A quoted value did not coerce
Quoted values intentionally stay strings.
parseJSON('{ enabled: "false" }')
// => { enabled: 'false' }Remove the quotes for booleans:
parseJSON('{ enabled: false }')
// => { enabled: false }safeParse returns undefined
That means strict parsing failed and no default was provided.
safeParse("{'loose': true}", {})
// => {}Comments are not removed
Comment-like text inside strings is preserved. Do not rely on this package as a comment-stripping parser.
parseJSON('"// not a comment"')
// => '// not a comment'Limitations
- Not a schema validator.
- Not a full JavaScript parser.
- Not a full JSON5 implementation.
- Not recommended as the first parser for untrusted server request bodies.
- Extremely malformed input may still throw.
FAQ
Does it parse normal JSON?
Yes. Strict JSON is tried first.
Does it preserve falsy JSON root values?
Yes. parseJSON('null'), parseJSON('0'), parseJSON('false'), and parseJSON('""') return null, 0, false, and ''.
Does it mutate objects I pass in?
No parser repair is applied to native objects and arrays. They are returned as JavaScript values.
Should I use this for HTTP request bodies?
Usually no. Use native JSON.parse, your framework's JSON body parser, or safeParse with a clear fallback.
Is this a JSON5 parser?
No. It supports some overlapping loose syntax, but it is a forgiving parser for practical CLI/config inputs rather than a JSON5 implementation.
License
MIT
