Commit 55c04e32 authored by Kamal Marhubi's avatar Kamal Marhubi

JSON: encode NaNs and infinite floats as `null`

Such values are not allowed by the JSON spec. We match the behavior of
JSON.stringify in Firefox and Chrome.

fixes https://github.com/sandstorm-io/capnproto/issues/261
parent cb17739b
......@@ -127,8 +127,8 @@ const char ALL_TYPES_JSON[] =
" \"uInt16List\": [33333, 44444],\n"
" \"uInt32List\": [3333333333],\n"
" \"uInt64List\": [\"11111111111111111111\"],\n"
" \"float32List\": [5555.5, inf, -inf, nan],\n"
" \"float64List\": [7777.75, inf, -inf, nan],\n"
" \"float32List\": [5555.5, null, null, null],\n"
" \"float64List\": [7777.75, null, null, null],\n"
" \"textList\": [\"plugh\", \"xyzzy\", \"thud\"],\n"
" \"dataList\": [[111, 111, 112, 115], [101, 120, 104, 97, 117, 115, 116, 101, 100], [114, 102, 99, 51, 48, 57, 50]],\n"
" \"structList\": [\n"
......
......@@ -20,6 +20,7 @@
// THE SOFTWARE.
#include "json.h"
#include <cmath>
#include <unordered_map>
#include <kj/debug.h>
......@@ -237,9 +238,20 @@ void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder
case schema::Type::UINT8:
case schema::Type::UINT16:
case schema::Type::UINT32:
output.setNumber(input.as<double>());
break;
case schema::Type::FLOAT32:
case schema::Type::FLOAT64:
output.setNumber(input.as<double>());
{
double value = input.as<double>();
if (std::isinf(value) || std::isnan(value)) {
// These values are not allowed in the JSON spec. Setting the field as null matches the
// behavior of JSON.stringify in Firefox and Chrome.
output.setNull();
} else {
output.setNumber(value);
}
}
break;
case schema::Type::INT64:
output.setString(kj::str(input.as<int64_t>()));
......
......@@ -48,6 +48,8 @@ class JsonCodec {
// - When encoding, all primitive fields are always encoded, even if default-valued. Pointer
// fields are only encoded if they are non-null.
// - 64-bit integers are encoded as strings, since JSON "numbers" are double-precision floating
// - NaNs and infinite floating point numbers are not allowed by the JSON spec, and so are encoded
// as null. This matches the behavior of `JSON.stringify` in at least Firefox and Chrome.
// points which cannot store a 64-bit integer without losing data.
// - Data is encoded as an array of numbers in the range [0,255]. You probably want to register
// a handler that does something better, like maybe base64 encoding, but there are a zillion
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment