ramonhagenaars / jsons

🐍 A Python lib for (de)serializing Python objects to/from JSON
https://jsons.readthedocs.io
MIT License
288 stars 40 forks source link

Avoid hashed keys when json-key-compatible serializer is set for key type, avoid errors on strict with hashed keys #150

Closed georgeharker closed 2 years ago

georgeharker commented 2 years ago

For

class Foo(NamedTuple):
    a: int
    b: int
    c: int

@dataclass
class D:
    a: int
    b: int

bar: Dict[Foo, D] = {Foo(1, 2, 3): D(a=42, b=39)}
dumped = jsons.dump(
    bar, cls=Dict[Foo, D],
    strict=True,
    strip_privates=True,
    strip_properties=True,
    use_enum_name = True)
loaded = jsons.load(
    dumped, cls=Dict[Foo, D],
    strict=True,
    strip_privates=True,
    strip_properties=True,
    use_enum_name = True)

jsons would previously crash on the load

class Foo(NamedTuple):
    a: int
    b: int
    c: int

@dataclass
class D:
    a: int
    b: int

def foo_serializer(obj, **kwargs):
    return "{},{},{}".format(obj.a, obj.b, obj.c)

def foo_deserializer(obj, cls, **kwargs):
    res = obj.split(',')
    return Foo(
        a = int(res[0]),
        b = int(res[1]),
        c = int(res[2]))

jsons.set_serializer(foo_serializer, Foo,  True)
jsons.set_deserializer(foo_deserializer, Foo,  True)

bar: Dict[Foo, D] = {Foo(1, 2, 3): D(a=42, b=39)}
dumped = jsons.dump(
    bar, cls=Dict[Foo, D],
    strict=True,
    strip_privates=True,
    strip_properties=True,
    use_enum_name = True)
loaded = jsons.load(
    dumped, cls=Dict[Foo, D],
    strict=True,
    strip_privates=True,
    strip_properties=True,
    use_enum_name = True)

would crash on load with strict mode and without would still use hashed keys despite the serialized key being json compatible.

This change corrects both and determines whether key hashing is required per key.

codecov-commenter commented 2 years ago

Codecov Report

Merging #150 (31eb91d) into master (fc1f21b) will decrease coverage by 0.93%. The diff coverage is 94.33%.

Impacted file tree graph

@@             Coverage Diff             @@
##            master     #150      +/-   ##
===========================================
- Coverage   100.00%   99.06%   -0.94%     
===========================================
  Files           57       60       +3     
  Lines         1413     1490      +77     
===========================================
+ Hits          1413     1476      +63     
- Misses           0       14      +14     
Impacted Files Coverage Δ
jsons/_dump_impl.py 100.00% <ø> (ø)
jsons/serializers/default_datetime.py 100.00% <ø> (ø)
jsons/_compatibility_impl.py 92.00% <50.00%> (-8.00%) :arrow_down:
jsons/deserializers/default_zone_info.py 88.88% <88.88%> (ø)
jsons/serializers/default_primitive.py 94.73% <91.66%> (-5.27%) :arrow_down:
jsons/__init__.py 100.00% <100.00%> (ø)
jsons/_cache.py 100.00% <100.00%> (ø)
jsons/_datetime_impl.py 100.00% <100.00%> (ø)
jsons/_package_info.py 100.00% <100.00%> (ø)
jsons/deserializers/default_dict.py 100.00% <100.00%> (ø)
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 390ea48...31eb91d. Read the comment docs.