diff --git a/bson/json_util.py b/bson/json_util.py index 05fa0e2ec..b9e088943 100644 --- a/bson/json_util.py +++ b/bson/json_util.py @@ -17,9 +17,9 @@ This module provides two helper methods `dumps` and `loads` that wrap the native :mod:`json` methods and provide explicit BSON conversion to and from JSON. :class:`~bson.json_util.JSONOptions` provides a way to control how JSON -is emitted and parsed, with the default being the legacy PyMongo format. -:mod:`~bson.json_util` can also generate Canonical or Relaxed `Extended JSON`_ -when :const:`CANONICAL_JSON_OPTIONS` or :const:`RELAXED_JSON_OPTIONS` is +is emitted and parsed, with the default being the Relaxed Extended JSON format. +:mod:`~bson.json_util` can also generate Canonical or legacy `Extended JSON`_ +when :const:`CANONICAL_JSON_OPTIONS` or :const:`LEGACY_JSON_OPTIONS` is provided, respectively. .. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json.rst @@ -32,7 +32,7 @@ Example usage (deserialization): >>> loads('[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]') [{'foo': [1, 2]}, {'bar': {'hello': 'world'}}, {'code': Code('function x() { return 1; }', {})}, {'bin': Binary(b'...', 128)}] -Example usage (serialization): +Example usage with :const:`RELAXED_JSON_OPTIONS` (the default): .. doctest:: @@ -40,9 +40,9 @@ Example usage (serialization): >>> from bson.json_util import dumps >>> dumps([{'foo': [1, 2]}, ... {'bar': {'hello': 'world'}}, - ... {'code': Code("function x() { return 1; }", {})}, + ... {'code': Code("function x() { return 1; }")}, ... {'bin': Binary(b"\x01\x02\x03\x04")}]) - '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]' + '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' Example usage (with :const:`CANONICAL_JSON_OPTIONS`): @@ -57,18 +57,18 @@ Example usage (with :const:`CANONICAL_JSON_OPTIONS`): ... json_options=CANONICAL_JSON_OPTIONS) '[{"foo": [{"$numberInt": "1"}, {"$numberInt": "2"}]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' -Example usage (with :const:`RELAXED_JSON_OPTIONS`): +Example usage (with :const:`LEGACY_JSON_OPTIONS`): .. doctest:: >>> from bson import Binary, Code - >>> from bson.json_util import dumps, RELAXED_JSON_OPTIONS + >>> from bson.json_util import dumps, LEGACY_JSON_OPTIONS >>> dumps([{'foo': [1, 2]}, ... {'bar': {'hello': 'world'}}, - ... {'code': Code("function x() { return 1; }")}, + ... {'code': Code("function x() { return 1; }", {})}, ... {'bin': Binary(b"\x01\x02\x03\x04")}], - ... json_options=RELAXED_JSON_OPTIONS) - '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' + ... json_options=LEGACY_JSON_OPTIONS) + '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]' Alternatively, you can manually pass the `default` to :func:`json.dumps`. It won't handle :class:`~bson.binary.Binary` and :class:`~bson.code.Code` @@ -238,23 +238,27 @@ class JSONOptions(CodecOptions): .. seealso:: The specification for Relaxed and Canonical `Extended JSON`_. - .. versionadded:: 3.4 + .. versionchanged:: 4.0 + The default for `json_mode` was changed from :const:`JSONMode.LEGACY` + to :const:`JSONMode.RELAXED`. .. versionchanged:: 3.5 Accepts the optional parameter `json_mode`. + .. versionadded:: 3.4 """ - def __new__(cls, strict_number_long=False, - datetime_representation=DatetimeRepresentation.LEGACY, - strict_uuid=False, json_mode=JSONMode.LEGACY, + def __new__(cls, strict_number_long=None, + datetime_representation=None, + strict_uuid=None, json_mode=JSONMode.RELAXED, *args, **kwargs): kwargs["tz_aware"] = kwargs.get("tz_aware", True) if kwargs["tz_aware"]: kwargs["tzinfo"] = kwargs.get("tzinfo", utc) if datetime_representation not in (DatetimeRepresentation.LEGACY, DatetimeRepresentation.NUMBERLONG, - DatetimeRepresentation.ISO8601): + DatetimeRepresentation.ISO8601, + None): raise ConfigurationError( "JSONOptions.datetime_representation must be one of LEGACY, " "NUMBERLONG, or ISO8601 from DatetimeRepresentation.") @@ -267,17 +271,47 @@ class JSONOptions(CodecOptions): "or CANONICAL from JSONMode.") self.json_mode = json_mode if self.json_mode == JSONMode.RELAXED: + if strict_number_long: + raise ConfigurationError( + "Cannot specify strict_number_long=True with" + " JSONMode.RELAXED") + if datetime_representation not in (None, + DatetimeRepresentation.ISO8601): + raise ConfigurationError( + "datetime_representation must be DatetimeRepresentation." + "ISO8601 or omitted with JSONMode.RELAXED") + if strict_uuid not in (None, True): + raise ConfigurationError( + "Cannot specify strict_uuid=False with JSONMode.RELAXED") self.strict_number_long = False self.datetime_representation = DatetimeRepresentation.ISO8601 self.strict_uuid = True elif self.json_mode == JSONMode.CANONICAL: + if strict_number_long not in (None, True): + raise ConfigurationError( + "Cannot specify strict_number_long=False with" + " JSONMode.RELAXED") + if datetime_representation not in ( + None, DatetimeRepresentation.NUMBERLONG): + raise ConfigurationError( + "datetime_representation must be DatetimeRepresentation." + "NUMBERLONG or omitted with JSONMode.RELAXED") + if strict_uuid not in (None, True): + raise ConfigurationError( + "Cannot specify strict_uuid=False with JSONMode.RELAXED") self.strict_number_long = True self.datetime_representation = DatetimeRepresentation.NUMBERLONG self.strict_uuid = True - else: - self.strict_number_long = strict_number_long - self.datetime_representation = datetime_representation - self.strict_uuid = strict_uuid + else: # JSONMode.LEGACY + self.strict_number_long = False + self.datetime_representation = DatetimeRepresentation.LEGACY + self.strict_uuid = False + if strict_number_long is not None: + self.strict_number_long = strict_number_long + if datetime_representation is not None: + self.datetime_representation = datetime_representation + if strict_uuid is not None: + self.strict_uuid = strict_uuid return self def _arguments_repr(self): @@ -307,7 +341,7 @@ class JSONOptions(CodecOptions): >>> from bson.json_util import CANONICAL_JSON_OPTIONS >>> CANONICAL_JSON_OPTIONS.tz_aware True - >>> json_options = CANONICAL_JSON_OPTIONS.with_options(tz_aware=False) + >>> json_options = CANONICAL_JSON_OPTIONS.with_options(tz_aware=False, tzinfo=None) >>> json_options.tz_aware False @@ -329,15 +363,6 @@ LEGACY_JSON_OPTIONS = JSONOptions(json_mode=JSONMode.LEGACY) .. versionadded:: 3.5 """ -DEFAULT_JSON_OPTIONS = LEGACY_JSON_OPTIONS -"""The default :class:`JSONOptions` for JSON encoding/decoding. - -The same as :const:`LEGACY_JSON_OPTIONS`. This will change to -:const:`RELAXED_JSON_OPTIONS` in a future release. - -.. versionadded:: 3.4 -""" - CANONICAL_JSON_OPTIONS = JSONOptions(json_mode=JSONMode.CANONICAL) """:class:`JSONOptions` for Canonical Extended JSON. @@ -354,18 +379,16 @@ RELAXED_JSON_OPTIONS = JSONOptions(json_mode=JSONMode.RELAXED) .. versionadded:: 3.5 """ -STRICT_JSON_OPTIONS = JSONOptions( - strict_number_long=True, - datetime_representation=DatetimeRepresentation.ISO8601, - strict_uuid=True) -"""**DEPRECATED** - :class:`JSONOptions` for MongoDB Extended JSON's *Strict -mode* encoding. +DEFAULT_JSON_OPTIONS = RELAXED_JSON_OPTIONS +"""The default :class:`JSONOptions` for JSON encoding/decoding. + +The same as :const:`RELAXED_JSON_OPTIONS`. + +.. versionchanged:: 4.0 + Changed from :const:`LEGACY_JSON_OPTIONS` to + :const:`RELAXED_JSON_OPTIONS`. .. versionadded:: 3.4 - -.. versionchanged:: 3.5 - Deprecated. Use :const:`RELAXED_JSON_OPTIONS` or - :const:`CANONICAL_JSON_OPTIONS` instead. """ @@ -380,6 +403,10 @@ def dumps(obj, *args, **kwargs): encoding of MongoDB Extended JSON types. Defaults to :const:`DEFAULT_JSON_OPTIONS`. + .. versionchanged:: 4.0 + Now outputs MongoDB Relaxed Extended JSON by default (using + :const:`DEFAULT_JSON_OPTIONS`). + .. versionchanged:: 3.4 Accepts optional parameter `json_options`. See :class:`JSONOptions`. """ diff --git a/doc/changelog.rst b/doc/changelog.rst index 32b26d744..828d8b038 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -98,6 +98,12 @@ Breaking Changes in 4.0 - Removed :exc:`pymongo.errors.CertificateError`. - Removed :attr:`pymongo.GEOHAYSTACK`. - Removed :class:`bson.binary.UUIDLegacy`. +- Removed :const:`bson.json_util.STRICT_JSON_OPTIONS`. Use + :const:`~bson.json_util.RELAXED_JSON_OPTIONS` or + :const:`~bson.json_util.CANONICAL_JSON_OPTIONS` instead. +- Changed the default JSON encoding representation from legacy to relaxed. + The json_mode parameter for :const:`bson.json_util.dumps` now defaults to + :const:`~bson.json_util.RELAXED_JSON_OPTIONS`. - The "tls" install extra is no longer necessary or supported and will be ignored by pip. - The ``hint`` option is now required when using ``min`` or ``max`` queries diff --git a/doc/migrate-to-pymongo3.rst b/doc/migrate-to-pymongo3.rst index 9b30fc36f..c1a4c490a 100644 --- a/doc/migrate-to-pymongo3.rst +++ b/doc/migrate-to-pymongo3.rst @@ -124,9 +124,7 @@ modifier. Code like this:: # Set a 5 second select() timeout. >>> cursor = collection.find({"a": 1}, network_timeout=5) -can be changed to this with PyMongo 2.9 or later: - -.. doctest:: +can be changed to this with PyMongo 2.9 or later:: # Set a 5 second (5000 millisecond) server side query timeout. >>> cursor = collection.find({"a": 1}, modifiers={"$maxTimeMS": 5000}) diff --git a/doc/migrate-to-pymongo4.rst b/doc/migrate-to-pymongo4.rst index 2ae78a1a1..2394f29ca 100644 --- a/doc/migrate-to-pymongo4.rst +++ b/doc/migrate-to-pymongo4.rst @@ -675,6 +675,13 @@ can be changed to this:: uu = uuid.uuid4() uuid_legacy = Binary.from_uuid(uu, PYTHON_LEGACY) +Default JSONMode changed from LEGACY to RELAXED +----------------------------------------------- + +Changed the default JSON encoding representation from legacy to relaxed. +The json_mode parameter for :const:`bson.json_util.dumps` now defaults to +:const:`~bson.json_util.RELAXED_JSON_OPTIONS`. + Removed features with no migration path --------------------------------------- diff --git a/gridfs/grid_file.py b/gridfs/grid_file.py index 606cf98d1..3e455dc93 100644 --- a/gridfs/grid_file.py +++ b/gridfs/grid_file.py @@ -658,7 +658,7 @@ class GridOut(io.IOBase): def __iter__(self): """Return an iterator over all of this file's data. - The iterator will return lines (delimited by b'\n') of + The iterator will return lines (delimited by ``b'\\n'``) of :class:`bytes`. This can be useful when serving files using a webserver that handles such an iterator efficiently. diff --git a/test/test_bson_corpus.py b/test/test_bson_corpus.py index 6590d00a3..98a4cf305 100644 --- a/test/test_bson_corpus.py +++ b/test/test_bson_corpus.py @@ -71,7 +71,8 @@ codec_options_uuid_04 = codec_options._replace(uuid_representation=STANDARD) json_options_uuid_04 = json_util.JSONOptions(json_mode=JSONMode.CANONICAL, uuid_representation=STANDARD) json_options_iso8601 = json_util.JSONOptions( - datetime_representation=json_util.DatetimeRepresentation.ISO8601) + datetime_representation=json_util.DatetimeRepresentation.ISO8601, + json_mode=JSONMode.LEGACY) to_extjson = functools.partial(json_util.dumps, json_options=json_util.CANONICAL_JSON_OPTIONS) to_extjson_uuid_04 = functools.partial(json_util.dumps, diff --git a/test/test_json_util.py b/test/test_json_util.py index 5b6efbc63..c20c793d3 100644 --- a/test/test_json_util.py +++ b/test/test_json_util.py @@ -24,7 +24,9 @@ sys.path[0:0] = [""] from bson import json_util, EPOCH_AWARE, SON from bson.json_util import (DatetimeRepresentation, - STRICT_JSON_OPTIONS) + JSONMode, + JSONOptions, + LEGACY_JSON_OPTIONS) from bson.binary import (ALL_UUID_REPRESENTATIONS, Binary, MD5_SUBTYPE, USER_DEFINED_SUBTYPE, UuidRepresentation, STANDARD) from bson.code import Code @@ -40,6 +42,13 @@ from bson.tz_util import FixedOffset, utc from test import unittest, IntegrationTest +STRICT_JSON_OPTIONS = JSONOptions( + strict_number_long=True, + datetime_representation=DatetimeRepresentation.ISO8601, + strict_uuid=True, + json_mode=JSONMode.LEGACY) + + class TestJsonUtil(unittest.TestCase): def round_tripped(self, doc, **kwargs): return json_util.loads(json_util.dumps(doc, **kwargs), **kwargs) @@ -51,16 +60,18 @@ class TestJsonUtil(unittest.TestCase): self.round_trip({"hello": "world"}) def test_json_options_with_options(self): - opts = json_util.JSONOptions( - datetime_representation=DatetimeRepresentation.NUMBERLONG) + opts = JSONOptions( + datetime_representation=DatetimeRepresentation.NUMBERLONG, + json_mode=JSONMode.LEGACY) self.assertEqual( opts.datetime_representation, DatetimeRepresentation.NUMBERLONG) opts2 = opts.with_options( - datetime_representation=DatetimeRepresentation.ISO8601) + datetime_representation=DatetimeRepresentation.ISO8601, + json_mode=JSONMode.LEGACY) self.assertEqual( opts2.datetime_representation, DatetimeRepresentation.ISO8601) - opts = json_util.JSONOptions(strict_number_long=True) + opts = JSONOptions(strict_number_long=True, json_mode=JSONMode.LEGACY) self.assertEqual(opts.strict_number_long, True) opts2 = opts.with_options(strict_number_long=False) self.assertEqual(opts2.strict_number_long, False) @@ -152,11 +163,17 @@ class TestJsonUtil(unittest.TestCase): pre_epoch = {"dt": datetime.datetime(1, 1, 1, 1, 1, 1, 10000, utc)} post_epoch = {"dt": datetime.datetime(1972, 1, 1, 1, 1, 1, 10000, utc)} self.assertEqual( - '{"dt": {"$date": -62135593138990}}', + '{"dt": {"$date": {"$numberLong": "-62135593138990"}}}', json_util.dumps(pre_epoch)) self.assertEqual( - '{"dt": {"$date": 63075661010}}', + '{"dt": {"$date": "1972-01-01T01:01:01.010Z"}}', json_util.dumps(post_epoch)) + self.assertEqual( + '{"dt": {"$date": -62135593138990}}', + json_util.dumps(pre_epoch, json_options=LEGACY_JSON_OPTIONS)) + self.assertEqual( + '{"dt": {"$date": 63075661010}}', + json_util.dumps(post_epoch, json_options=LEGACY_JSON_OPTIONS)) self.assertEqual( '{"dt": {"$date": {"$numberLong": "-62135593138990"}}}', json_util.dumps(pre_epoch, json_options=STRICT_JSON_OPTIONS)) @@ -164,8 +181,9 @@ class TestJsonUtil(unittest.TestCase): '{"dt": {"$date": "1972-01-01T01:01:01.010Z"}}', json_util.dumps(post_epoch, json_options=STRICT_JSON_OPTIONS)) - number_long_options = json_util.JSONOptions( - datetime_representation=DatetimeRepresentation.NUMBERLONG) + number_long_options = JSONOptions( + datetime_representation=DatetimeRepresentation.NUMBERLONG, + json_mode=JSONMode.LEGACY) self.assertEqual( '{"dt": {"$date": {"$numberLong": "63075661010"}}}', json_util.dumps(post_epoch, json_options=number_long_options)) @@ -194,14 +212,14 @@ class TestJsonUtil(unittest.TestCase): datetime.datetime(1972, 1, 1, 1, 1, 1, 10000, utc), json_util.loads( '{"dt": {"$date": "1972-01-01T01:01:01.010+0000"}}', - json_options=json_util.JSONOptions(tz_aware=True, + json_options=JSONOptions(tz_aware=True, tzinfo=utc))["dt"]) self.assertEqual( datetime.datetime(1972, 1, 1, 1, 1, 1, 10000), json_util.loads( '{"dt": {"$date": "1972-01-01T01:01:01.010+0000"}}', - json_options=json_util.JSONOptions(tz_aware=False))["dt"]) - self.round_trip(pre_epoch_naive, json_options=json_util.JSONOptions( + json_options=JSONOptions(tz_aware=False))["dt"]) + self.round_trip(pre_epoch_naive, json_options=JSONOptions( tz_aware=False)) # Test a non-utc timezone @@ -211,10 +229,12 @@ class TestJsonUtil(unittest.TestCase): self.assertEqual( '{"dt": {"$date": "2002-10-27T06:00:00.010-0800"}}', json_util.dumps(aware_datetime, json_options=STRICT_JSON_OPTIONS)) - self.round_trip(aware_datetime, json_options=json_util.JSONOptions( + self.round_trip(aware_datetime, json_options=JSONOptions( + json_mode=JSONMode.LEGACY, tz_aware=True, tzinfo=pacific)) - self.round_trip(aware_datetime, json_options=json_util.JSONOptions( + self.round_trip(aware_datetime, json_options=JSONOptions( datetime_representation=DatetimeRepresentation.ISO8601, + json_mode=JSONMode.LEGACY, tz_aware=True, tzinfo=pacific)) def test_regex_object_hook(self): @@ -253,13 +273,18 @@ class TestJsonUtil(unittest.TestCase): # Check order. self.assertEqual( - '{"$regex": ".*", "$options": "mx"}', + '{"$regularExpression": {"pattern": ".*", "options": "mx"}}', json_util.dumps(Regex('.*', re.M | re.X))) self.assertEqual( - '{"$regex": ".*", "$options": "mx"}', + '{"$regularExpression": {"pattern": ".*", "options": "mx"}}', json_util.dumps(re.compile(b'.*', re.M | re.X))) + self.assertEqual( + '{"$regex": ".*", "$options": "mx"}', + json_util.dumps(Regex('.*', re.M | re.X), + json_options=LEGACY_JSON_OPTIONS)) + def test_minkey(self): self.round_trip({"m": MinKey()}) @@ -278,26 +303,28 @@ class TestJsonUtil(unittest.TestCase): self.round_trip(doc) self.assertEqual( '{"uuid": {"$uuid": "f47ac10b58cc4372a5670e02b2c3d479"}}', - json_util.dumps(doc)) + json_util.dumps(doc, json_options=LEGACY_JSON_OPTIONS)) self.assertEqual( '{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}', json_util.dumps( - doc, json_options=json_util.STRICT_JSON_OPTIONS)) + doc, json_options=STRICT_JSON_OPTIONS)) self.assertEqual( '{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}', json_util.dumps( - doc, json_options=json_util.JSONOptions( - strict_uuid=True, uuid_representation=STANDARD))) + doc, json_options=JSONOptions( + strict_uuid=True, json_mode=JSONMode.LEGACY, + uuid_representation=STANDARD))) self.assertEqual( doc, json_util.loads( '{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}')) for uuid_representation in (set(ALL_UUID_REPRESENTATIONS) - {UuidRepresentation.UNSPECIFIED}): - options = json_util.JSONOptions( - strict_uuid=True, uuid_representation=uuid_representation) + options = JSONOptions( + strict_uuid=True, json_mode=JSONMode.LEGACY, + uuid_representation=uuid_representation) self.round_trip(doc, json_options=options) # Ignore UUID representation when decoding BSON binary subtype 4. self.assertEqual(doc, json_util.loads( @@ -307,8 +334,9 @@ class TestJsonUtil(unittest.TestCase): def test_uuid_uuid_rep_unspecified(self): _uuid = uuid.uuid4() - options = json_util.JSONOptions( + options = JSONOptions( strict_uuid=True, + json_mode=JSONMode.LEGACY, uuid_representation=UuidRepresentation.UNSPECIFIED) # Cannot directly encode native UUIDs with UNSPECIFIED. @@ -329,7 +357,8 @@ class TestJsonUtil(unittest.TestCase): doc, json_util.loads(ext_json_str, json_options=options)) # $uuid-encoded fields doc = {'uuid': Binary(_uuid.bytes, subtype=4)} - ext_json_str = json_util.dumps({'uuid': _uuid}) + ext_json_str = json_util.dumps({'uuid': _uuid}, + json_options=LEGACY_JSON_OPTIONS) self.assertEqual( doc, json_util.loads(ext_json_str, json_options=options)) @@ -350,11 +379,13 @@ class TestJsonUtil(unittest.TestCase): self.assertEqual(type(bin), bytes) # PYTHON-443 ensure old type formats are supported - json_bin_dump = json_util.dumps(bin_type_dict) - self.assertTrue('"$type": "00"' in json_bin_dump) + json_bin_dump = json_util.dumps(bin_type_dict, + json_options=LEGACY_JSON_OPTIONS) + self.assertIn('"$type": "00"', json_bin_dump) self.assertEqual(bin_type_dict, json_util.loads('{"bin": {"$type": 0, "$binary": "AAECAwQ="}}')) - json_bin_dump = json_util.dumps(md5_type_dict) + json_bin_dump = json_util.dumps(md5_type_dict, + json_options=LEGACY_JSON_OPTIONS) # Check order. self.assertEqual( '{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==",' @@ -365,8 +396,9 @@ class TestJsonUtil(unittest.TestCase): json_util.loads('{"md5": {"$type": 5, "$binary":' ' "IG43GK8JL9HRL4DK53HMrA=="}}')) - json_bin_dump = json_util.dumps(custom_type_dict) - self.assertTrue('"$type": "80"' in json_bin_dump) + json_bin_dump = json_util.dumps(custom_type_dict, + json_options=LEGACY_JSON_OPTIONS) + self.assertIn('"$type": "80"', json_bin_dump) self.assertEqual(custom_type_dict, json_util.loads('{"custom": {"$type": 128, "$binary":' ' "aGVsbG8="}}')) @@ -404,7 +436,8 @@ class TestJsonUtil(unittest.TestCase): Int64(65535)) self.assertEqual(json_util.dumps({"weight": Int64(65535)}), '{"weight": 65535}') - json_options = json_util.JSONOptions(strict_number_long=True) + json_options = JSONOptions(strict_number_long=True, + json_mode=JSONMode.LEGACY) self.assertEqual(json_util.dumps({"weight": Int64(65535)}, json_options=json_options), jsn) @@ -413,10 +446,10 @@ class TestJsonUtil(unittest.TestCase): # document_class dict should always work self.assertEqual({"foo": "bar"}, json_util.loads( '{"foo": "bar"}', - json_options=json_util.JSONOptions(document_class=dict))) + json_options=JSONOptions(document_class=dict))) self.assertEqual(SON([("foo", "bar"), ("b", 1)]), json_util.loads( '{"foo": "bar", "b": 1}', - json_options=json_util.JSONOptions(document_class=SON))) + json_options=JSONOptions(document_class=SON))) class TestJsonUtilRoundtrip(IntegrationTest):