In my post on the ColdFusion 901 release, more than one user commented that they weren't happy with the changes to JSON serialization in 901. According to the docs, the idea was that numbers wouldn't be converted to floats. Specifically, 10 would not become 10.0. Also, values that had a leading 0, like 007, would not lose their zeros and would become strings: "007". It appears though as if all of these values are turning into strings. So 10 becomes "10". This is contrary to what the docs say will happen. I disagreed with how serious this was, but to be honest, I really don't see any reason why the number needs to be quoted. Reader Patrick logged bug 83638. If you agree that the behavior should be fixed, than please add your vote. (And remember to click the Subscribe button to be notified of updates.) I just added my own vote.
Archived Comments
Can you explain why it matters if numbers are quoted or not? When I handroll JSON output I quote everything.
It matters because JSON has data types and Adobe isn't adhering to them. This becomes more of an issue when you are exchanging data with other systems that use JSON to hydrate an object with types in it. If it is expecting an integer and you send it "10" then you aren't sending it an integer, you are sending it a string. This will cause a type mismatch and it will blow up.
I haven't tested it in CF9, but CF hasn't dealt with null values well in JSON. When I have a .Net system send me a JSON packet and it has a key with a null value, it will come through correctly as key: null in the JSON packet. DeserializeJSON won't know what to do with it, however, since CF doesn't really have a concept of null. Consequently, I have to go through, treat the incoming JSON as a string, replace all instances of null with '' and then deserialize it. Fun fun.
I'm not sure where I stand on this (though I voted for the bug yesterday). At least making everything a string makes it consistent and predictable -- though I sympathize with people for whom this breaks code.
I haven't upgraded to 9.0.1, but I wonder if the changes affect the way booleans are treated as well. In 9.0 the following produces "true", which may or may not be what you want:
#serializeJSON("Yes")#
Keeping the Backward compatibility issue in mind, we have provided a JVM property "json.numberasdouble". By setting this to true, one can go back to old behavior where a number or boolean value will not get quoted.
The reason for this is because CF's old behavior was counter intuitive and destructive. Not only would it truncate "007" potentially removing important formatting, it would also destroy certain numbers.
In CF do x = "10000055555001111111193299".
That number can't be represented precisely in an IEEE754 double so if CF converted it to a floating point number and then sent it to JS you'd get the wrong number on the other side. There was no way around this before, CF always converted the numbers (which was wrong). Serial numbers are a quick way to get numbers that are of this length.
You can see this behavior in JS if you do:
10000055555001111111193299-10000055555001111111193290
The result is zero, not 9.
JS has very loose typing and quoted numbers should be fine. If your code is expecting a number using json.value-0 is the best way to go, though Number(json.value) works too. parseInt() has bad behavior if you pass it the wrong value ("5+x" becomes 5) and it's also quite slow, and would be noticeable on a large data set.
You could also get bitten if a user passed a numeric value in previous versions of CF. If a user entered "5" in a form for the username and in JS you had code that did json.username.toUpperCase() your code would suddenly fail because CF returned a number (instead of a string as you'd expect from most input). We got bitten by this on several occasions and had to add String() around the JSON.
The new behavior removes all those time bomb bugs from existing code bases and makes the result of serializeJSON() safe and predictable.
Ray - glad to see you agree with my original complaint from July 13th. From what I've seen since everything is returned as strings. Also seeing things like returning a struct with two integers and simply incrementing one (using ++ operator) before returning then the incremented value has decimal .0 added.
Actually an important point I forgot to mention is I'm not using serializeJSON() - in my case I'm using CFCs with returnformat="json". I'm not sure if CF uses the same serializeJSON code to handle returning CFC data.
@Johans: CF uses the same code path as serailzeJson() to serialize the data in case one uses CFCs with returnformat="json".
When I clicked the Bug link, it's not found in Adobe's database. What gives?
I think 901 bugs are hidden now because the tracker is still in "901 isn't released yet" mode.
I did receive an email from Adobe on Aug 11:
Fixed In: ColdFusion 9.0.1 ,HotFix, Build 274873
Description: The patch notes state that the int to float bug has been fixed. It says that 10 will turn to 10, 012 will turn to "012" (which is fine) and 10.25 will turn to 10.25 in JSON representation. However all numbers are just turned to strings.
Get the hot fix now:
http://kb2.adobe.com/cps/86...
Holy crap! We finally had occasion to jump to .0.1 on our server and it broke SO MANY AJAX INTERFACES on SO MANY OF OUR PRODUCTION SITES. Thank god for the hotfix. That was traumatic.