ramonhagenaars / jsons

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

hashed-key dicts with strict crash #147

Closed georgeharker closed 2 years ago

georgeharker commented 3 years ago

Consider:

from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, NamedTuple

import jsons

class TT(IntEnum):
    TA = 0
    TB = 1

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

@dataclass
class D:
    a: int
    b: int

@dataclass
class Bar:
    t: Dict[Foo, D] = field(default_factory = dict)

s = jsons.dumps(Bar(t={Foo(1, TT.TA, 3): D(a=42, b=39)}), cls=Bar,
                strict=True,
                strip_privates=True,
                strip_properties=True,
                use_enum_name = True)
b = jsons.loads(s, cls=Bar,
                strict=True,
                strip_privates=True,
                strip_properties=True,
                use_enum_name = True)
print(s, b)

Without the strict settings this prints

{"t": {"-keys": {"-6883746737928644908": {"a": 1, "b": 0, "c": 3}}, "-6883746737928644908": {"a": 42, "b": 39}}} Bar(t={Foo(a=1, b=<TT.TA: 0>, c=3): D(a=42, b=39)})

Because of the use of strict, when default_dict_deserializer attempts to deserialize -keys it fully decodes the key, and then attempts to be decoded again during the subsequent decode of the dict values / construction of the result. I have a hack that returns whether _load_hashed_keys found stored keys, and skips the duplicate deserialize on the keys in that case, but it's probably a bit ugly, and I wonder whether there's a cleaner fix.

georgeharker commented 3 years ago

See here for a proposed fix that seems relatively clean. Not quite sure how to up the coverage numbers.

ramonhagenaars commented 2 years ago

Thank you @georgeharker. I've checked your bugreport and your fix for it and it seems good to me. I will make a release for it.