Skip to content

Commit 42fd42d

Browse files
committed
fixes to_json() method chokes on some standard json.dumps() such as
sort_keys #490
1 parent f1d87e9 commit 42fd42d

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

deepdiff/serialization.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def from_json_pickle(cls, value):
179179
else:
180180
logger.error('jsonpickle library needs to be installed in order to run from_json_pickle') # pragma: no cover. Json pickle is getting deprecated.
181181

182-
def to_json(self, default_mapping=None, **kwargs):
182+
def to_json(self, default_mapping: dict | None=None, force_use_builtin_json=False, **kwargs):
183183
"""
184184
Dump json of the text view.
185185
**Parameters**
@@ -190,6 +190,11 @@ def to_json(self, default_mapping=None, **kwargs):
190190
If you have a certain object type that the json serializer can not serialize it, please pass the appropriate type
191191
conversion through this dictionary.
192192
193+
force_use_builtin_json: Boolean, default = False
194+
When True, we use Python's builtin Json library for serialization,
195+
even if Orjson is installed.
196+
197+
193198
kwargs: Any other kwargs you pass will be passed on to Python's json.dumps()
194199
195200
**Example**
@@ -212,7 +217,12 @@ def to_json(self, default_mapping=None, **kwargs):
212217
'{"type_changes": {"root": {"old_type": "A", "new_type": "B", "old_value": "obj A", "new_value": "obj B"}}}'
213218
"""
214219
dic = self.to_dict(view_override=TEXT_VIEW)
215-
return json_dumps(dic, default_mapping=default_mapping, **kwargs)
220+
return json_dumps(
221+
dic,
222+
default_mapping=default_mapping,
223+
force_use_builtin_json=force_use_builtin_json,
224+
**kwargs,
225+
)
216226

217227
def to_dict(self, view_override=None):
218228
"""
@@ -637,14 +647,26 @@ def object_hook(self, obj):
637647
return obj
638648

639649

640-
def json_dumps(item, default_mapping=None, **kwargs):
650+
def json_dumps(item, default_mapping=None, force_use_builtin_json: bool=False, **kwargs):
641651
"""
642652
Dump json with extra details that are not normally json serializable
653+
654+
parameters
655+
----------
656+
657+
force_use_builtin_json: Boolean, default = False
658+
When True, we use Python's builtin Json library for serialization,
659+
even if Orjson is installed.
643660
"""
644-
if orjson:
661+
if orjson and not force_use_builtin_json:
645662
indent = kwargs.pop('indent', None)
646663
if indent:
647664
kwargs['option'] = orjson.OPT_INDENT_2
665+
if 'sort_keys' in kwargs:
666+
raise TypeError(
667+
"orjson does not accept the sort_keys parameter. "
668+
"If you need to pass sort_keys, set force_use_builtin_json=True "
669+
"to use Python's built-in json library instead of orjson.")
648670
return orjson.dumps(
649671
item,
650672
default=json_convertor_default(default_mapping=default_mapping),

tests/test_serialization.py

+8
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ def test_serialization_text(self):
4747
jsoned = ddiff.to_json()
4848
assert "world" in jsoned
4949

50+
def test_serialization_text_force_builtin_json(self):
51+
ddiff = DeepDiff(t1, t2)
52+
with pytest.raises(TypeError) as excinfo:
53+
jsoned = ddiff.to_json(sort_keys=True)
54+
assert str(excinfo.value).startswith("orjson does not accept the sort_keys parameter.")
55+
jsoned = ddiff.to_json(sort_keys=True, force_use_builtin_json=True)
56+
assert "world" in jsoned
57+
5058
def test_deserialization(self):
5159
ddiff = DeepDiff(t1, t2)
5260
jsoned = ddiff.to_json_pickle()

0 commit comments

Comments
 (0)