Note that we can't preserve key order in json_util.dumps in Python 2.4, PYTHON-602.
This commit is contained in:
parent
c672b8c3cb
commit
2f67eff07e
@ -47,6 +47,10 @@ It won't handle :class:`~bson.binary.Binary` and :class:`~bson.code.Code`
|
||||
instances (as they are extended strings you can't provide custom defaults),
|
||||
but it will be faster as there is less recursion.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
Preserves order when rendering SON, Timestamp, Code, Binary, and DBRef
|
||||
instances. (But not in Python 2.4.)
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
Added dumps and loads helpers to automatically handle conversion to and
|
||||
from json and supports :class:`~bson.binary.Binary` and
|
||||
@ -114,7 +118,7 @@ def dumps(obj, *args, **kwargs):
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
Preserves order when rendering SON, Timestamp, Code, Binary, and DBRef
|
||||
instances.
|
||||
instances. (But not in Python 2.4.)
|
||||
"""
|
||||
if not json_lib:
|
||||
raise Exception("No json library available")
|
||||
@ -193,6 +197,14 @@ def object_hook(dct, compile_re=True):
|
||||
|
||||
|
||||
def default(obj):
|
||||
# We preserve key order when rendering SON, DBRef, etc. as JSON by
|
||||
# returning a SON for those types instead of a dict. This works with
|
||||
# the "json" standard library in Python 2.6+ and with simplejson
|
||||
# 2.1.0+ in Python 2.5+, because those libraries iterate the SON
|
||||
# using PyIter_Next. Python 2.4 must use simplejson 2.0.9 or older,
|
||||
# and those versions of simplejson use the lower-level PyDict_Next,
|
||||
# which bypasses SON's order-preserving iteration, so we lose key
|
||||
# order in Python 2.4.
|
||||
if isinstance(obj, ObjectId):
|
||||
return {"$oid": str(obj)}
|
||||
if isinstance(obj, DBRef):
|
||||
|
||||
@ -40,6 +40,7 @@ from bson.tz_util import utc
|
||||
from test.test_client import get_client
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
PY24 = sys.version_info[:2] == (2, 4)
|
||||
|
||||
|
||||
class TestJsonUtil(unittest.TestCase):
|
||||
@ -70,10 +71,11 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.round_trip({"ref": DBRef("foo", 5, "db")})
|
||||
self.round_trip({"ref": DBRef("foo", ObjectId())})
|
||||
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$ref": "collection", "$id": 1, "$db": "db"}',
|
||||
json_util.dumps(DBRef('collection', 1, 'db')))
|
||||
if not PY24:
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$ref": "collection", "$id": 1, "$db": "db"}',
|
||||
json_util.dumps(DBRef('collection', 1, 'db')))
|
||||
|
||||
def test_datetime(self):
|
||||
# only millis, not micros
|
||||
@ -130,14 +132,15 @@ class TestJsonUtil(unittest.TestCase):
|
||||
'{"r": {"$regex": ".*", "$options": "ilm"}}',
|
||||
compile_re=False)['r'])
|
||||
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(Regex('.*', re.M | re.X)))
|
||||
if not PY24:
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(Regex('.*', re.M | re.X)))
|
||||
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(re.compile(b('.*'), re.M | re.X)))
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(re.compile(b('.*'), re.M | re.X)))
|
||||
|
||||
def test_minkey(self):
|
||||
self.round_trip({"m": MinKey()})
|
||||
@ -146,10 +149,12 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.round_trip({"m": MaxKey()})
|
||||
|
||||
def test_timestamp(self):
|
||||
res = json_util.json.dumps({"ts": Timestamp(4, 13)},
|
||||
default=json_util.default)
|
||||
self.assertEqual('{"ts": {"t": 4, "i": 13}}', res)
|
||||
dct = json_util.json.loads(res)
|
||||
res = json_util.dumps({"ts": Timestamp(4, 13)}, default=json_util.default)
|
||||
if not PY24:
|
||||
# Check order.
|
||||
self.assertEqual('{"ts": {"t": 4, "i": 13}}', res)
|
||||
|
||||
dct = json_util.loads(res)
|
||||
self.assertEqual(dct['ts']['t'], 4)
|
||||
self.assertEqual(dct['ts']['i'], 13)
|
||||
|
||||
@ -178,9 +183,12 @@ class TestJsonUtil(unittest.TestCase):
|
||||
json_util.loads('{"bin": {"$type": 0, "$binary": "AAECAwQ="}}'))
|
||||
|
||||
json_bin_dump = json_util.dumps(md5_type_dict)
|
||||
self.assertEqual(
|
||||
'{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==", "$type": "05"}}',
|
||||
json_bin_dump)
|
||||
if not PY24:
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==",'
|
||||
+ ' "$type": "05"}}',
|
||||
json_bin_dump)
|
||||
|
||||
self.assertEqual(md5_type_dict,
|
||||
json_util.loads('{"md5": {"$type": 5, "$binary":'
|
||||
@ -208,8 +216,9 @@ class TestJsonUtil(unittest.TestCase):
|
||||
res = json_util.dumps(code)
|
||||
self.assertEqual(code, json_util.loads(res))
|
||||
|
||||
# Check order.
|
||||
self.assertEqual('{"$code": "return z", "$scope": {"z": 2}}', res)
|
||||
if not PY24:
|
||||
# Check order.
|
||||
self.assertEqual('{"$code": "return z", "$scope": {"z": 2}}', res)
|
||||
|
||||
def test_cursor(self):
|
||||
db = self.db
|
||||
|
||||
Loading…
Reference in New Issue
Block a user