Is it correct that JSON.stringify(2) == "2" may return false?
Asked Answered
S

1

27

I've found that on Opera 11.50 the expression

 JSON.stringify(2)

returns an object for which

  • typeof returns "string"
  • constructor.name is String
  • charCodeAt(0) is 50
  • length is 1

But still

alert(JSON.stringify(2) == "2")

shows "false" in Opera (and the same happens using ===).

Is this a bug or what?

The only way I found to make it compare equal to "2" is calling .substr(0) (for example even adding an empty string still compares different).

Subsocial answered 14/8, 2011 at 16:39 Comment(16)
If it is so then it is a bug. Minimalistic sample to try would be helpful to say for sure.Waw
Interesting, == 2 yields true...Archaeological
does look like a bug, however I found that this is true: JSON.stringify(2) == 2Pathe
Yup, it's a bug. I've tried every work around I can think of but it still returns false. ;_;Devault
Does it also return false if you use x === "2" ?Win
@c-smile: added the code exampleSubsocial
First guess would be that the 2 inside JSON.stringify(2) is not actually exactly 2 due to floating point error but then the string returned would also reflect that :/Ignorant
If x = JSON.stringify(2), then x.toString(), String(x), x + "" etc. all return false. Weird... x - 0 + "" == "2" does return true, as does x + "1" == "21".Wanettawanfried
@aero: I'm not sure I understand your point. I'm checking the strings... (and anyway the problem is present using the literal 2 as shown in the code example)Subsocial
Another interesting thing is that the bug occurs with and only with numbers 0 to 9.Molina
How interesting, that I'm not suprised. Opera is crazy!Brusa
I suspect it has to do with the fact that new String("2") !== "2".Overcautious
@Dan Tao: No, if that was it then (JSON.stringify(2) + '') == "2" would fix it.Evans
There, I fixed it ;) var js = JSON.stringify; JSON.stringify = function(input) { return js(input).substr(); }; `Selfstarter
@Pumbaa80: close, but no cigar. JSON.stringify(undefined) should be undefined, that implementation instead throws an exception.Subsocial
Ah right, I also forgot to consider the optional arguments :)Selfstarter
K
7

That definitely looks like a bug.

From the ECMAScript 5.1 specification:

Conforming implementations of JSON.parse and JSON.stringify must support the exact interchange format described in this specification without any deletions or extensions to the format. This differs from RFC 4627 which permits a JSON parser to accept non-JSON forms and extensions.

And:

JSON.stringify produces a String that conforms to the following JSON grammar. JSON.parse accepts a String that conforms to the JSON grammar

It may be that it somehow wraps the string in a "JSONText" type object which still has a typeof of string but that seems very odd.

I would definitely think that the following implementation in this case is the correct one:

JSON.stringify(2) == "2" && JSON.stringify(2) === "2" && JSON.stringify(2) == 2 && JSON.stringify(2) !== 2;
true

According to @6502 (see comment) this is true in:
Chrome; Firefox; IE9; iPad Safari; OsX Safari; the N1 Android browser

The ECMAScript 5.1 specification document: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

Kwa answered 14/8, 2011 at 17:45 Comment(7)
Actually it works correctly on chrome, firefox, IE9, iPad and OsX versions of Safari and even the N1 Android browser. The fact this only happens with single-digit numbers makes me wonder if it's because of some sort of optimization trick...Subsocial
Have you posted a bug report yet? Rather than an optimization trick I assume a bug in some loop in the stringify algorithm, but we'll never know since Opera's source code is not publicly available.Selfstarter
Yes it's annoying that we can't just look in the code. Though I couldn't be bothered anyway. I haven't submitted a bug report as I don't use opera and didn't observe the bug myself. I think the OP should do so.Kwa
I submitted a report once for a rendering problem (that by the way looked like a buffer overflow: I was sure in that case it was a bug because what got rendered wrong was the letter "m" and not something i was drawing myself). I never got any reply or requests for infos (not even a "die off") and so I decided that I'm not going to waste more time with them. I'm not using opera for browsing, I use it just to check if what I write works there too. In this case I wasn't sure because js is often quite illogical ... (I originally thought it could have been a problem related to tainting).Subsocial
The bug should be fixed in Opera 12, if it isn't already in the current snapshots. @6502: Typically bugs don't get personal responses, for a variety of reasons. Got the bug number for what you did report? Should be in the automated email response.Knockabout
@gsnedders: I ended up subitting a bug report anyway (I always look worse than I really am...). This bug code is DSK-344615, the bug about the rendering problem was DSK-335956. By the way what is the rationale of giving bug IDs to public reports if there's no public bug tracker? Why not giving at least access to the tracker page of the specific bug?Subsocial
@6502: The bug IDs are only given out indirectly as a means to give follow-up information, which is really just by virtue of how JIRA works. Giving access to a single bug would effectively make almost all of our bugs public, which we've decided not to do. But the objection of many internally (myself included) to it being private in general isn't exactly a secret...Knockabout

© 2022 - 2024 — McMap. All rights reserved.