diff --git a/bson/json_util.py b/bson/json_util.py index 983573edc..925897e94 100644 --- a/bson/json_util.py +++ b/bson/json_util.py @@ -48,7 +48,13 @@ instances (as they are extended strings you can't provide custom defaults), but it will be faster as there is less recursion. .. versionchanged:: 2.8 - Supports $numberLong and $undefined - new in MongoDB 2.6. Also supports + The output format for :class:`~bson.timestamp.Timestamp` has changed from + '{"t": , "i": }' to '{"$timestamp": {"t": , "i": }}'. + This new format will be decoded to an instance of + :class:`~bson.timestamp.Timestamp`. The old format will continue to be + decoded to a python dict as before. Encoding to the old format is no longer + supported as it was never correct and loses type information. + Added support for $numberLong and $undefined - new in MongoDB 2.6 - and parsing $date in ISO-8601 format. .. versionchanged:: 2.7 @@ -232,6 +238,9 @@ def object_hook(dct, compile_re=True): # 2to3 will change this to int. PyMongo 3.0 supports # a new type, Int64, to avoid round trip issues. return long(dct["$numberLong"]) + if "$timestamp" in dct: + tsp = dct["$timestamp"] + return Timestamp(tsp["t"], tsp["i"]) return dct @@ -279,7 +288,7 @@ def default(obj): if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): - return SON([("t", obj.time), ("i", obj.inc)]) + return {"$timestamp": SON([("t", obj.time), ("i", obj.inc)])} if isinstance(obj, Code): return SON([('$code', str(obj)), ('$scope', obj.scope)]) if isinstance(obj, Binary): diff --git a/doc/changelog.rst b/doc/changelog.rst index 1ff913f6e..35d00b882 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -30,6 +30,13 @@ Highlights include: - :meth:`~pymongo.mongo_client.MongoClient.copy_database` - :class:`~pymongo.master_slave_connection.MasterSlaveConnection` + The JSON format for :class:`~bson.timestamp.Timestamp` has changed from + '{"t": , "i": }' to '{"$timestamp": {"t": , "i": }}'. + This new format will be decoded to an instance of + :class:`~bson.timestamp.Timestamp`. The old format will continue to be + decoded to a python dict as before. Encoding to the old format is no + longer supported as it was never correct and loses type information. + Issues Resolved ............... diff --git a/test/test_json_util.py b/test/test_json_util.py index 861cf02d0..8b6a7dd94 100644 --- a/test/test_json_util.py +++ b/test/test_json_util.py @@ -177,14 +177,14 @@ class TestJsonUtil(unittest.TestCase): self.round_trip({"m": MaxKey()}) def test_timestamp(self): - res = json_util.dumps({"ts": Timestamp(4, 13)}, default=json_util.default) + dct = {"ts": Timestamp(4, 13)} + res = json_util.dumps(dct, default=json_util.default) if not PY24: # Check order. - self.assertEqual('{"ts": {"t": 4, "i": 13}}', res) + self.assertEqual('{"ts": {"$timestamp": {"t": 4, "i": 13}}}', res) - dct = json_util.loads(res) - self.assertEqual(dct['ts']['t'], 4) - self.assertEqual(dct['ts']['i'], 13) + rtdct = json_util.loads(res) + self.assertEqual(dct, rtdct) def test_uuid(self): if not bson.has_uuid():