New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior of JSON.stringify() #741

Closed
adius opened this Issue Nov 26, 2016 · 7 comments

Comments

Projects
None yet
5 participants
@adius

adius commented Nov 26, 2016

JSON.stringify({[new Date()]: 'test'})

yields

{
  "Sat Nov 26 2016 13:46:13 GMT+0000 (UTC)": "test"
}

but I would expect it to yield

{
  "2016-11-26T13:46:13.923Z": "test"
}
@ljharb

This comment has been minimized.

Show comment
Hide comment
@ljharb

ljharb Nov 26, 2016

Member

new Date().toString() produces the former, the latter is new Date().toISOString(). The conversion happens when the Date object is coerced to a string to become the object property key. Object.keys({[new Date()]: 'test'})[0] will produce the same string value - JSON.stringify doesn't come into it.

Member

ljharb commented Nov 26, 2016

new Date().toString() produces the former, the latter is new Date().toISOString(). The conversion happens when the Date object is coerced to a string to become the object property key. Object.keys({[new Date()]: 'test'})[0] will produce the same string value - JSON.stringify doesn't come into it.

@adius

This comment has been minimized.

Show comment
Hide comment
@adius

adius Nov 26, 2016

I just realized that, too 🙈.

What I was thinking of in the first place was rather: new Map([[new Date(), 'test']])
…and actually the yield of JSON.stringify(new Map([[new Date(), 'test']])) is also not optimal.

It should rather be {"2016-11-26T14:15:55.380Z": "test"} instead of [["2016-11-26T14:15:55.380Z","test"]].

adius commented Nov 26, 2016

I just realized that, too 🙈.

What I was thinking of in the first place was rather: new Map([[new Date(), 'test']])
…and actually the yield of JSON.stringify(new Map([[new Date(), 'test']])) is also not optimal.

It should rather be {"2016-11-26T14:15:55.380Z": "test"} instead of [["2016-11-26T14:15:55.380Z","test"]].

@ljharb

This comment has been minimized.

Show comment
Hide comment
@ljharb

ljharb Nov 26, 2016

Member

In fact, it can't, because Maps can have objects as keys, and object keys themselves can only be strings or Symbols. An array of entries (where an "entry" is an array of key, value) is the only way a Map can be represented in a serializable fashion.

Member

ljharb commented Nov 26, 2016

In fact, it can't, because Maps can have objects as keys, and object keys themselves can only be strings or Symbols. An array of entries (where an "entry" is an array of key, value) is the only way a Map can be represented in a serializable fashion.

@adius

This comment has been minimized.

Show comment
Hide comment
@adius

adius Nov 26, 2016

is the only way a Map can be represented in a serializable fashion

Yeah, I guess you're right. Otherwise you would have to serialize simple maps as JSON Objects and complex maps as JSON Arrays, which would be very confusing.

Maybe there should be a JSON.stringifyMap() method which simply stringifies each key…

adius commented Nov 26, 2016

is the only way a Map can be represented in a serializable fashion

Yeah, I guess you're right. Otherwise you would have to serialize simple maps as JSON Objects and complex maps as JSON Arrays, which would be very confusing.

Maybe there should be a JSON.stringifyMap() method which simply stringifies each key…

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan

littledan Nov 26, 2016

Member

Keys of objects are already strings or symbols when constructed. So it would be a little late for that

Member

littledan commented Nov 26, 2016

Keys of objects are already strings or symbols when constructed. So it would be a little late for that

@benjamn

This comment has been minimized.

Show comment
Hide comment
@benjamn

benjamn Nov 26, 2016

Member

There are a variety of libraries that attempt to improve on JSON by supporting stringification of objects with prototypes other than Object.prototype or Array.prototype, along with circular and repeated references, another common JSON.stringify gotcha.

Two that come to mind are lave and arson (full disclosure: I am the author of arson).

Here's how the example might work:

> const { encode, decode } = require("arson")
undefined
> map = new Map
Map {}
> map.set(new Date, "test")
Map { 2016-11-26T17:34:28.448Z => 'test' }
> encode(map)
'[["Map",1],[2,3],["Date",4],"test","2016-11-26T17:34:28.448Z"]'
> decode(_)
Map { 2016-11-26T17:34:28.448Z => 'test' }

More examples in the README.md.

Member

benjamn commented Nov 26, 2016

There are a variety of libraries that attempt to improve on JSON by supporting stringification of objects with prototypes other than Object.prototype or Array.prototype, along with circular and repeated references, another common JSON.stringify gotcha.

Two that come to mind are lave and arson (full disclosure: I am the author of arson).

Here's how the example might work:

> const { encode, decode } = require("arson")
undefined
> map = new Map
Map {}
> map.set(new Date, "test")
Map { 2016-11-26T17:34:28.448Z => 'test' }
> encode(map)
'[["Map",1],[2,3],["Date",4],"test","2016-11-26T17:34:28.448Z"]'
> decode(_)
Map { 2016-11-26T17:34:28.448Z => 'test' }

More examples in the README.md.

@adius

This comment has been minimized.

Show comment
Hide comment
@adius

adius Nov 26, 2016

Thanks for the tip!

adius commented Nov 26, 2016

Thanks for the tip!

@bterlson bterlson added the question label Nov 26, 2016

@bterlson bterlson closed this Nov 26, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment