Is JSON.stringify () deterministic in V8?

I have not seen (yet?) JSON.stringifyBe non-deterministic in Node.JS.

There is no guarantee that it will be deterministic at the specification level.

But what about the V8; Is its implementation there deterministic? Is there any guarantee that it will remain deterministic for future versions of V8?

Edit:

With determinate, I mean that the following statement is true, regardless of value json_str. (Given that this value is a valid JSON string.)

const obj = JSON.parse(json_str);
assert(JSON.stringify(obj)===JSON.stringify(obj)); // always true

Edit 2:

Actually, Iโ€™m also interested in making the following statement true.

if( deepEqual(obj1, obj2) ) {
    assert(JSON.stringify(obj1)===JSON.stringify(obj2))
}

what is wrong (see answers).

+4
source share
4

jmrk;

, , :

var o = {};
o[2] = 2;
o.a = 3;
o.b = 4;
o["1"] = 1;

assert(JSON.stringify(o)==='{"1":1,"2":2,"a":3,"b":4}');

:

if( obj1 === obj2 ) {
  assert(JSON.stringify(obj1) === JSON.stringify(obj2));
}

" " ;

var obj1 = {};
obj1["a"] = true;
obj1["b"] = true;
assert(JSON.stringify(obj1)==='{"a":true,"b":true}');

var obj2 = {};
obj2["b"] = true;
obj2["a"] = true;
assert(JSON.stringify(obj2)==='{"b":true,"a":true}');

,

  • .
  • P of O, , , do

    . P .

  • P O, , , do

    . P .

  • P of O, , , do

    . P .

  • .

https://tc39.imtqy.com/ecma262/#sec-ordinaryownpropertykeys

+5

"" : , V8 . . https://tc39.imtqy.com/ecma262/#sec-ordinaryownpropertykeys. [: , , JSON.stringify .]

"" " ", , , : -)

> var o = { toJSON: function() { return Math.random(); } }
> JSON.stringify(o);
< "0.37377773963616434"
> JSON.stringify(o);
< "0.8877065604993732"

Proxy replacer JSON.stringify ( JSON.stringify ).

"" - , , .

+5

:

  • Order = > ?

, "".

  1. = > ?

, , JSON, @jmrk, .

  1. Concurrency = > ?

, V8 script runner - , .

  1. = > , ?

, /, .

  1. = > stringify ?

No, the specification is not clear in the order in which the fields of the Object are listed, so implementations can freely sort through objects, which means that the data can be the same for the โ€œtargetโ€ and โ€œspiritโ€, and not comparable by bytes.

Hope this helps!

+2
source

In case someone searches for a function that makes JSON prediction predictable, I wrote one:

const sortObj = (obj) => (
  obj === null || typeof obj !== 'object'
  ? obj
  : Array.isArray(obj)
  ? obj.map(sortObj)
  : Object.assign({}, 
      ...Object.entries(obj)
        .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
        .map(([k, v]) => ({ [k]: sortObj(v) }),
    ))
);

Here's a complex deterministic JSON dump:

const deterministicStrigify = obj => JSON.stringify(deterministic(sortObj))

This works well with the examples above:

> obj1 = {};
> obj1.b = 5;
> obj1.a = 15;

> obj2 = {};
> obj2.a = 15;
> obj2.b = 5;

> deterministicStrigify(obj1)
'{"a":15,"b":5}'
> deterministicStrigify(obj2)
'{"a":15,"b":5}'
> JSON.stringify(obj1)
'{"b":5,"a":15}'
> JSON.stringify(obj2)
'{"a":15,"b":5}'
+2
source

Source: https://habr.com/ru/post/1670954/


All Articles