json-stringifier
v0.1.0
Published
Alternative to JSON.stringify() that supports altering the behavior of the stringification process at string level
Downloads
2,286
Maintainers
Readme
json-stringifier
Alternative to JSON.stringify()
that supports altering the behavior of the
stringification process at string level.
Rationale
It's common to use objects in immutable fashion. We could optimize the
serialization of these objects by caching their JSON representation. However,
there's no way to achieve this using built-in JSON.stringify()
function: its
replacer
parameter only allows substituting serialized values, but not resulting strings.
stringify()
function provided by this library accepts a stringifier
parameter that lets us override the stringification of values in the object
tree. See Memoization example.
Another use case is when you have a strict schema for some objects inside your
object tree. With this library you can use
fast-json-stringify
for
these objects and the regular stringification for the rest.
Installation
$ npm install json-stringifier
Examples
Memoization
Custom stringifier that memoizes JSON representations of objects:
import {stringify} from 'json-stringifier';
const cache = new WeakMap();
function memoizedStringify(value) {
if (value !== null && typeof value === 'object') {
if (cache.has(value)) {
return cache.get(value);
} else {
const json = stringify(value, memoizedStringify);
cache.set(value, json);
return json;
}
}
return stringify(value, memoizedStringify);
}
let state = {
obj: {a: 1},
arr: [1, 2, 3],
};
memoizedStringify(state); // '{"obj":{"a":1},"arr":[1,2,3]}'
state = {
...state,
arr: [4, 5, 6],
};
memoizedStringify(state); // state.obj stringification is bypassed
Handling Circular References
Custom stringifier that handles circular references:
function safeStringify(value, seen) {
if (value !== null && typeof value === 'object') {
if (seen && seen.has(value)) {
return '"<circular>"';
}
if (seen == null) {
seen = new Set();
}
seen.add(value);
const json = stringify(value, child => safeStringify(child, seen));
seen.delete(value);
return json;
}
return stringify(value);
}
const obj = {};
obj.self = obj;
obj.child = {parent: obj};
safeStringify(obj); // '{"self":"<circular>","child":{"parent":"<circular>"}}'
Support Additional Structures
Custom stringifier that supports Sets and Maps:
function customStringify(value) {
if (value instanceof Set) {
return stringify({'@@type': 'Set', values: [...value]}, customStringify);
}
if (value instanceof Map) {
return stringify({'@@type': 'Map', entries: [...value]}, customStringify);
}
return stringify(value, customStringify);
}
customStringify({
set: new Set([1, 2, 3]),
map: new Map([[1, 'a'], [2, 'b'], [3, 'c']])),
});
// '{"set":{"@@type":"Set","values":[1,2,3]},"map":{"@@type":"Map","entries":[[1,"a"],[2,"b"],[3,"c"]]}}'
API
stringifier(value, stringify = stringifier)
value
— The value to convert to a JSON string.stringify
(optional) — A function that is called to get the JSON string for each property value whenvalue
is an object, or each element whenvalue
is an array.stringify
is called with a single argument — the property value or array element and must return a string orundefined
. Note thatstringify
is not called with thevalue
itself. Defaults tostringifier
, which gives recursive stringification.- Returns a JSON string representing the given value or
undefined
ifvalue
isundefined
, a function or a symbol.
Comparison with JSON.stringify()
stringify(value)
behaves mostly the same as JSON.stringify(value)
with few
exceptions:
toJSON()
is always called with no arguments.- Primitive wrapper types
Boolean
,Number
andString
are not supported (yet).