diff --git a/CHANGES.txt b/CHANGES.txt index 950b43b9b655c8729f2a8c556bdda7f926c4282c_Q0hBTkdFUy50eHQ=..3ba3d5b3ea1968bf8b3516d683b3d612d263692a_Q0hBTkdFUy50eHQ= 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,6 +5,8 @@ key, rather than the original object. This ensures that the sort only compares string types and makes the behavior consistent between Python 2.x and Python 3.x. +* Like other number types, Decimal instances used as keys are now + coerced to strings when use_decimal is True. Version 2.6.2 released 2012-09-21 diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c index 950b43b9b655c8729f2a8c556bdda7f926c4282c_c2ltcGxlanNvbi9fc3BlZWR1cHMuYw==..3ba3d5b3ea1968bf8b3516d683b3d612d263692a_c2ltcGxlanNvbi9fc3BlZWR1cHMuYw== 100644 --- a/simplejson/_speedups.c +++ b/simplejson/_speedups.c @@ -2739,6 +2739,11 @@ if (kstr == NULL) goto bail; } + else if (s->use_decimal && PyObject_TypeCheck(key, (PyTypeObject *)s->Decimal)) { + kstr = PyObject_Str(key); + if (kstr == NULL) + goto bail; + } else if (skipkeys) { Py_DECREF(item); continue; diff --git a/simplejson/encoder.py b/simplejson/encoder.py index 950b43b9b655c8729f2a8c556bdda7f926c4282c_c2ltcGxlanNvbi9lbmNvZGVyLnB5..3ba3d5b3ea1968bf8b3516d683b3d612d263692a_c2ltcGxlanNvbi9lbmNvZGVyLnB5 100644 --- a/simplejson/encoder.py +++ b/simplejson/encoder.py @@ -440,7 +440,7 @@ del markers[markerid] def _stringify_key(key): - if isinstance(key, string_types): + if isinstance(key, string_types): # pragma: no cover pass elif isinstance(key, binary_type): key = key.decode(_encoding) @@ -454,6 +454,8 @@ key = 'null' elif isinstance(key, integer_types): key = str(key) + elif _use_decimal and isinstance(key, Decimal): + key = str(key) elif _skipkeys: key = None else: diff --git a/simplejson/tests/test_decimal.py b/simplejson/tests/test_decimal.py index 950b43b9b655c8729f2a8c556bdda7f926c4282c_c2ltcGxlanNvbi90ZXN0cy90ZXN0X2RlY2ltYWwucHk=..3ba3d5b3ea1968bf8b3516d683b3d612d263692a_c2ltcGxlanNvbi90ZXN0cy90ZXN0X2RlY2ltYWwucHk= 100644 --- a/simplejson/tests/test_decimal.py +++ b/simplejson/tests/test_decimal.py @@ -28,7 +28,15 @@ for s in self.NUMS: self.assertEquals(self.loads(s, parse_float=Decimal), Decimal(s)) + def test_stringify_key(self): + for d in map(Decimal, self.NUMS): + v = {d: d} + self.assertEquals( + self.loads( + self.dumps(v, use_decimal=True), parse_float=Decimal), + {str(d): d}) + def test_decimal_roundtrip(self): for d in map(Decimal, self.NUMS): # The type might not be the same (int and Decimal) but they # should still compare equal. @@ -31,15 +39,12 @@ def test_decimal_roundtrip(self): for d in map(Decimal, self.NUMS): # The type might not be the same (int and Decimal) but they # should still compare equal. - self.assertEquals( - self.loads( - self.dumps(d, use_decimal=True), parse_float=Decimal), - d) - self.assertEquals( - self.loads( - self.dumps([d], use_decimal=True), parse_float=Decimal), - [d]) + for v in [d, [d], {'': d}]: + self.assertEquals( + self.loads( + self.dumps(v, use_decimal=True), parse_float=Decimal), + v) def test_decimal_defaults(self): d = Decimal('1.1') diff --git a/simplejson/tests/test_dump.py b/simplejson/tests/test_dump.py index 950b43b9b655c8729f2a8c556bdda7f926c4282c_c2ltcGxlanNvbi90ZXN0cy90ZXN0X2R1bXAucHk=..3ba3d5b3ea1968bf8b3516d683b3d612d263692a_c2ltcGxlanNvbi90ZXN0cy90ZXN0X2R1bXAucHk= 100644 --- a/simplejson/tests/test_dump.py +++ b/simplejson/tests/test_dump.py @@ -1,5 +1,5 @@ from unittest import TestCase -from simplejson.compat import StringIO, long_type +from simplejson.compat import StringIO, long_type, b import simplejson as json class TestDump(TestCase): @@ -8,6 +8,29 @@ json.dump({}, sio) self.assertEquals(sio.getvalue(), '{}') + def test_constants(self): + for c in [None, True, False]: + self.assert_(json.loads(json.dumps(c)) is c) + self.assert_(json.loads(json.dumps([c]))[0] is c) + self.assert_(json.loads(json.dumps({'a': c}))['a'] is c) + + def test_stringify_key(self): + items = [(b('bytes'), 'bytes'), + (1.0, '1.0'), + (10, '10'), + (True, 'true'), + (False, 'false'), + (None, 'null'), + (long_type(100), '100')] + for k, expect in items: + self.assertEquals( + json.loads(json.dumps({k: expect})), + {expect: expect}) + self.assertRaises(TypeError, json.dumps, {json: 1}) + self.assertEquals( + json.loads(json.dumps({json: 1}, skipkeys=True)), + {}) + def test_dumps(self): self.assertEquals(json.dumps({}), '{}') diff --git a/simplejson/tests/test_float.py b/simplejson/tests/test_float.py index 950b43b9b655c8729f2a8c556bdda7f926c4282c_c2ltcGxlanNvbi90ZXN0cy90ZXN0X2Zsb2F0LnB5..3ba3d5b3ea1968bf8b3516d683b3d612d263692a_c2ltcGxlanNvbi90ZXN0cy90ZXN0X2Zsb2F0LnB5 100644 --- a/simplejson/tests/test_float.py +++ b/simplejson/tests/test_float.py @@ -2,5 +2,6 @@ from unittest import TestCase from simplejson.compat import long_type, text_type import simplejson as json +from simplejson.decoder import NaN, PosInf, NegInf class TestFloat(TestCase): @@ -5,5 +6,12 @@ class TestFloat(TestCase): + def test_degenerates(self): + for inf in (PosInf, NegInf): + self.assertEquals(json.loads(json.dumps(inf)), inf) + # Python 2.5 doesn't have math.isnan + nan = json.loads(json.dumps(NaN)) + self.assert_((0 + nan) != nan) + def test_floats(self): for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: