diff --git a/lib/ultrajson.h b/lib/ultrajson.h index 1547aac..8334fca 100644 --- a/lib/ultrajson.h +++ b/lib/ultrajson.h @@ -166,6 +166,7 @@ enum JSTYPES JT_ARRAY, // Array structure JT_OBJECT, // Key/Value structure JT_INVALID, // Internal, do not return nor expect + JT_NAN, // Not A Number JT_POS_INF, // Positive infinity JT_NEG_INF, // Negative infinity }; @@ -323,6 +324,7 @@ typedef struct __JSONObjectDecoder JSOBJ (*newTrue)(void *prv); JSOBJ (*newFalse)(void *prv); JSOBJ (*newNull)(void *prv); + JSOBJ (*newNaN)(void *prv); JSOBJ (*newPosInf)(void *prv); JSOBJ (*newNegInf)(void *prv); JSOBJ (*newObject)(void *prv); diff --git a/lib/ultrajsondec.c b/lib/ultrajsondec.c index 2fad562..73e8a5d 100644 --- a/lib/ultrajsondec.c +++ b/lib/ultrajsondec.c @@ -201,9 +201,9 @@ DECODE_NAN: if (*(offset++) != 'a') goto SET_NAN_ERROR; if (*(offset++) != 'N') goto SET_NAN_ERROR; - ds->lastType = JT_NULL; + ds->lastType = JT_NAN; ds->start = offset; - return ds->dec->newNull(ds->prv); + return ds->dec->newNaN(ds->prv); SET_NAN_ERROR: return SetError(ds, -1, "Unexpected character found when decoding 'NaN'"); diff --git a/python/JSONtoObj.c b/python/JSONtoObj.c index a5085ef..f370bef 100644 --- a/python/JSONtoObj.c +++ b/python/JSONtoObj.c @@ -79,12 +79,17 @@ static JSOBJ Object_newNull(void *prv) Py_RETURN_NONE; } -JSOBJ Object_newPosInf(void *prv) +static JSOBJ Object_newNaN(void *prv) +{ + return PyFloat_FromDouble(Py_NAN); +} + +static JSOBJ Object_newPosInf(void *prv) { return PyFloat_FromDouble(Py_HUGE_VAL); } -JSOBJ Object_newNegInf(void *prv) +static JSOBJ Object_newNegInf(void *prv) { return PyFloat_FromDouble(-Py_HUGE_VAL); } @@ -139,6 +144,7 @@ PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs) Object_newTrue, Object_newFalse, Object_newNull, + Object_newNaN, Object_newPosInf, Object_newNegInf, Object_newObject, diff --git a/tests/test_ujson.py b/tests/test_ujson.py index d1c4573..58a8e96 100644 --- a/tests/test_ujson.py +++ b/tests/test_ujson.py @@ -671,11 +671,13 @@ def test_encode_raises_allow_nan(test_input, expected_exception): def test_nan_inf_support(): + import math text = '["a", NaN, "NaN", Infinity, "Infinity", -Infinity, "-Infinity"]' data = ujson.loads(text) - expected = ["a", float('nan'), "NaN", float('inf'), "Infinity", -float('inf'), "-Infinity"] + expected = ["a", float('nan'), "NaN", float('inf'), "Infinity", + -float('inf'), "-Infinity"] for a, b in zip(data, expected): - assert a == b or a is b + assert a == b or math.isnan(a) and math.isnan(b) @pytest.mark.parametrize(