json-es6
This packages json
object extends JSON. The package is appropriately named because of the following
three points.
- json extends JSON to all ES6 data types
- json.stringify() produces a string
s = json.stringify(x)
that is valid JavaScript - Evaluating the string via
const y = eval('( + s + ')'
produces a copy y of the original object x.
Because of (3), json.stringify(x) produces verbose strings. If x is a typed array, ArrayBuffer, or DataView, the results are especially verbose.
There is also a parse property, as in json.parse(s)
that also produces a copy of the original object.
This parse function does not use eval
in favor of real hard-core letter by letter parsing, whence
there are no safety issues.
Another design for json.parse()
is already made to be faster, but it is not debugged.
It will be put up in a later version.
Usage
npm install json-es6
const {json} = require('json-es6')
const s = json.stringify(x)
const y = eval('(' + s + ')') // y is a copy of x
const z = json.parse(s) // z is a copy of x
Example: Primitives and ES5 classes
const x =
{
a:undefined,
b:-Infinity,
c: -0,
d:12333333333333333333337777777777777777777777n,
e:true,
f:"cat",
g: new Boolean(true),
h: new Boolean(false),
i: new Number(7),
j: new String("cat"),
k: new Date(1234),
l: /abc/g,
}
json.stringify(x) is
{
"a":undefined,
"b":-Infinity,
"c":-0,
"d":12333333333333333333337777777777777777777777n,
"e":true,
"f":"cat",
"g":new Boolean(true),
"h":new Boolean(false),
"i":new Number(7),
"j":new String("cat"),
"k":new Date(1234),
"l":new RegExp('abc','g')
}
Example: Sets, Maps, and Typed Arrays
const x =
{
m: new Set(["cat", "dog", "hamster",
new Int16Array([-255, -256, -257])]),
n: new Map([[{a:1}, "cow"], ["horse", {b:2}]])
}
json.stringify(x) is
{
"m":new Set(
[
"cat",
"dog",
"hamster",
new Int16Array(
[
-255,
-256,
-257
])
]),
"n":new Map(
[
[
{
"a":1
},
"cow"
],
[
"horse",
{
"b":2
}
]
])
}
Example: Typed Arrays with Offsets
const x = new Int16Array(
new Uint16Array([-255,-256,-257,-258, -259, -230])
.buffer, 2,2)
json.stringify(x) is
new Int16Array(new Int16Array(
[
-255,
-256,
-257,
-258,
-259,
-230
]).buffer,2,2)
Example: ArrayBuffer
ArrayBuffers are written with Uint8Array encoding
const x = new Uint16Array([256, 257]).buffer
json.stringify(x) is
new Uint8Array(
[
0,
1,
1,
1
]).buffer
Example: DataView
DataViews are written with Uint8Array encoding.
const x = new DataView(new Uint16Array([256,257,258]).buffer)
json.stringfy(x) is
new DataView(new Uint8Array(
[
0,
1,
1,
1,
2,
1
]).buffer)
Example: DataView with Offset
const buffer = new Uint16Array([256, 257, 258, 259]).buffer
const x = new DataView(buffer, 2, 4)
json.stringfy(x) is
new DataView(new Uint8Array(
[
0,
1,
1,
1,
2,
1,
3,
1
]).buffer,2,4)
Example: WeakSets, WeakMaps, and Symbols
const x = {a:new WeakSet([...]), b:new WeakMap([...]), c: Symbol(...)}
json.stringify(x) is
{
"a":new WeakSet(),
"b":new WeakMap(),
"c":Symbol()
}
WeakSets and WeakMaps are written without any information about their internal state, because there is no access to their internal state. When read, new WeakSets and WeakMaps are created, which of course will have different internal states than their originals.
The discussion above for WeakSets and WeakMaps also holds for Symbols. But here,if there is a Symbol somewhere in the object tree, a JSON copy will never be deep-strict-equal because the target and source symbols will be different.
Example: Error and Error-Variant Classes
The stack property is not written, and so not read. Thus, if y = json.parse(json.stringify(x))
or equivalently if y = eval('(' + json.stringify(x) + ')'
then y is a deep copy of x, except
that corresponding error objects will have different stacks.
const x = {a:new Error("error message"), b:new RangeError("range error message")}
json.stringify(x) is
{
"a":new Error("error message"),
"b":new RangeError("range error message")
}
Testing
See the test folder. Copies are made through the json process, and verified with
a wrapper around assert.deepStrictEqual()
.
Verifying JSON copies is best done with assert.deepStrictEqual()
or deepStrictEqual()
from
the deep-equal-diagnostics package. Neither cares about the stack property of errors.
Neither cares if corresponding WeakSets and WeakMaps are not reference equal.
Again if Symbols are involved, the copy will never be deep-strict-equal to the original,
but their JSON strings will be identical.
Version History
|Version|Published|Description| |1.0.0|5-5-2022|Extend JSON to all of ES6|