json-es6

1.0.0 • Public • Published

json-es6

This packages json object extends JSON. The package is appropriately named because of the following three points.

  1. json extends JSON to all ES6 data types
  2. json.stringify() produces a string s = json.stringify(x) that is valid JavaScript
  3. 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|

/json-es6/

    Package Sidebar

    Install

    npm i json-es6

    Weekly Downloads

    1

    Version

    1.0.0

    License

    ISC

    Unpacked Size

    51.8 kB

    Total Files

    9

    Last publish

    Collaborators

    • markw9