Invalid JSON serialization of NaN values
Brought to you by:
artyom-beilis
Hi,
CppCMS's JSON encoding facility encodes NaN values as -1.#QNAN
(at least in my test case, with a particular data set, on MSVC 2012 / Windows). This isn't valid JSON and therefore causes client code to error out.
The applicable standard (ECMA-262) seems to specify that the correct serialization of any non-finite number values (NaNs, infinities, etc.) is null
.
Anonymous
Actually I'm not sure that using null is correct:
According to the link:
From there to: http://www.ecma-international.org/ecma-262/5.1/#sec-9.8
And then to http://www.ecma-international.org/ecma-262/5.1/#sec-9.8.1
NaN value should be converted to NaN.
But NaN is not part of the JSON specifications: http://www.json.org/
So technically NaN can't be presented in JSON.
Probably in case of NaN I should throw some kind of exception. Not sure thou.
Artyom, meaning no disrespect - CppCMS is cool, which is why I'm taking the time to do this :) - I think you went outside the JSON-relevant part of that specification.
Here's my more detailed take on the issue:
1) RFC 4627 says (on page 2):
2) ECMA 262 section 15.12.3 (the one I linked to) specifies the
JSON.stringify
function's behavior. I think you'll agree that this is an authoritative source on what JavaScript does in the equivalent case. JavaScript/ECMAScript has NaNs and infinities so there is indeed an exact equivalent case of "there's a NaN in my data - how does that translate to JSON?". Quoting the interesting parts:(Emphasis mine)
From #1 I gather that there is no JSON representation for NaNs and infinities. On its own, it would mean any implementation is free to do what it deems correct, including throwing an exception. But, in #2, JavaScript already sets an example for an implementation's behavior. And according to this example (which IMHO CppCMS should follow) it's not an error to try to serialize a NaN or Infinity to JSON - you just get a
null
out of it. So from the principle of least surprise (among other things), I think no exception should be thrown, at least not by default.For the record, my quick-and-dirty fix - assuming the silent conversion to
null
is desired - was:1) Add a usable implementation of
isfinite
from Boost ascppcms::json::detail::isfinite_impl()
(a proper solution would be to add the relevant parts of Boost.Math tocppcms_boost
and/or use an external Boost installation - I don't know the exact "CppCMS way" for this)2) In the implementation of
value::write_value()
in json.cpp, change:to