Skip to content

Commit 10baf2a

Browse files
committed
serializing properties
1 parent c7e581f commit 10baf2a

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

deepdiff/serialization.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,33 @@ def _convertor(obj):
643643
# This is to handle reverse() which creates a generator of type list_reverseiterator
644644
if obj.__class__.__name__ == 'list_reverseiterator':
645645
return list(copy(obj))
646-
raise TypeError('We do not know how to convert {} of type {} for json serialization. Please pass the default_mapping parameter with proper mapping of the object to a basic python type.'.format(obj, type(obj)))
646+
# 3) gather @property values by scanning __class__.__dict__ and bases
647+
props = {}
648+
for cls in obj.__class__.__mro__:
649+
for name, descriptor in cls.__dict__.items():
650+
if isinstance(descriptor, property) and not name.startswith('_'):
651+
try:
652+
props[name] = getattr(obj, name)
653+
except Exception:
654+
# skip properties that error out
655+
pass
656+
if props:
657+
return props
658+
659+
# 4) fallback: public __dict__ entries
660+
if hasattr(obj, '__dict__'):
661+
return {
662+
k: v
663+
for k, v in vars(obj).items()
664+
if not k.startswith('_')
665+
}
666+
667+
# 5) give up
668+
raise TypeError(
669+
f"Don't know how to JSON-serialize {obj!r} "
670+
f"(type {type(obj).__name__}); "
671+
"consider adding it to default_mapping."
672+
)
647673

648674
return _convertor
649675

tests/test_serialization.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ class B:
9191
t1 = A()
9292
t2 = B()
9393
ddiff = DeepDiff(t1, t2)
94-
with pytest.raises(TypeError):
95-
ddiff.to_json()
94+
assert r'{"type_changes":{"root":{"old_type":"A","new_type":"B","old_value":{},"new_value":{}}}}' == ddiff.to_json()
9695

9796
def test_serialize_custom_objects_with_default_mapping(self):
9897
class A:
@@ -206,6 +205,18 @@ def get_the_pickle():
206205
assert expected_msg == str(excinfo.value)
207206

208207

208+
def test_seriaize_property(self):
209+
210+
class Sample:
211+
@property
212+
def something(self):
213+
return 10
214+
215+
sample = Sample()
216+
serialized = json_dumps(sample)
217+
assert '{"something":10}' == serialized
218+
219+
209220
class TestDeepDiffPretty:
210221
"""Tests for pretty() method of DeepDiff"""
211222

0 commit comments

Comments
 (0)