@awsless/json
The @awsless/json package adds support for more JavaScript native types to JSON.
Features:
- Lightweight / Using the JS native JSON parser.
- JSON backwards compatible.
- No precision loss.
- Includes support basic JS types.
- Extendable.
The Problem
JSON doesn't have support for types like:
undefined
Set
Map
Date
BigInt
BigFloat - npm package @awsless/bit-float
Having to decode & encode these type of values can get quite annoying. We try to solve this problem by encoding these types using valid JSON syntax.
Also JSON.parse/stringify don't solve the potential loss of precision problem.
Basic Usage
import { parse, stringify } from '@awsless/json';
const json = stringify(1n)
const value = parse(json)
Patching incorrectly parsed JSON that was parsed with a different JSON parser
In some cases you might not have control over the JSON parser that is being used. In these cases your JSON will still be able to parse, but the output will be incorrect. We can patch the incorrect output by using the patch function.
import { stringify, patch } from '@awsless/json';
const json = stringify(1n)
const broken = JSON.parse(json)
const fixed = patch(broken)
Extending Supported Types
We let you extend JSON to support your own custom types.
import { parse, stringify, Serializable } from '@awsless/json';
class Custom {
readonly value
constructor(value: string) {
this.value = value
}
}
const $custom: Serializable<Custom, string> = {
is: v => v instanceof Custom,
parse: v => new Custom(v),
stringify: v => v.value,
}
const json = stringify(new Custom('example'), { $custom })
const value = parse(json, { $custom })
Precision Loss
When using the native JSON.parse/stringify functions you could lose precision when parsing native numbers. And you don't always have the ability to extend JSON with your own custom types. For example when you’re communicating with a third-party API. For this reason, we have 2 utility functions that will parse the native JSON number type to your own precision-safe alternative.
import { safeNumberParse, safeNumberStringify } from '@awsless/json';
import { BigFloat } from '@awsless/big-float';
const value = new BigFloat(1)
const json = safeNumberStringify(ONE, {
is: v => v instanceof BigFloat,
stringify: v => v.toString(),
})
console.log(json)
const result = safeNumberParse('1', {
parse: v => new BigFloat(v),
})
console.log(eq(value, result))
Known Issue's
Don't use the $ character inside your JSON.
We use the $ character to encode our special types inside JSON. In order to prevent parsing errors we recommend to avoid using the $ character inside your object property names.
Object properties with undefined as value type will be stripped away.
const result = parse(stringify({ key: undefined }))
console.log('key' in result)
console.log(result.key === undefined)