Python dataclass from a nested dict

后端 未结 10 747
孤街浪徒
孤街浪徒 2020-12-22 23:38

The standard library in 3.7 can recursively convert a dataclass into a dict (example from the docs):

from dataclasses import dataclass, asdict
from typing im         


        
相关标签:
10条回答
  • 2020-12-23 00:15

    undictify is a library which could be of help. Here is a minimal usage example:

    import json
    from dataclasses import dataclass
    from typing import List, NamedTuple, Optional, Any
    
    from undictify import type_checked_constructor
    
    
    @type_checked_constructor(skip=True)
    @dataclass
    class Heart:
        weight_in_kg: float
        pulse_at_rest: int
    
    
    @type_checked_constructor(skip=True)
    @dataclass
    class Human:
        id: int
        name: str
        nick: Optional[str]
        heart: Heart
        friend_ids: List[int]
    
    
    tobias_dict = json.loads('''
        {
            "id": 1,
            "name": "Tobias",
            "heart": {
                "weight_in_kg": 0.31,
                "pulse_at_rest": 52
            },
            "friend_ids": [2, 3, 4, 5]
        }''')
    
    tobias = Human(**tobias_dict)
    
    0 讨论(0)
  • 2020-12-23 00:18
    from validated_dc import ValidatedDC
    from dataclasses import dataclass
    
    from typing import List, Union
    
    
    @dataclass
    class Foo(ValidatedDC):
        foo: int
    
    
    @dataclass
    class Bar(ValidatedDC):
        bar: Union[Foo, List[Foo]]
    
    
    foo = {'foo': 1}
    instance = Bar(bar=foo)
    print(instance.get_errors())  # None
    print(instance)               # Bar(bar=Foo(foo=1))
    
    list_foo = [{'foo': 1}, {'foo': 2}]
    instance = Bar(bar=list_foo)
    print(instance.get_errors())  # None
    print(instance)               # Bar(bar=[Foo(foo=1), Foo(foo=2)])
    

    validated_dc:
    https://github.com/EvgeniyBurdin/validated_dc

    And see a more detailed example:
    https://github.com/EvgeniyBurdin/validated_dc/blob/master/examples/detailed.py

    0 讨论(0)
  • 2020-12-23 00:21

    You can use mashumaro for creating dataclass object from a dict according to the scheme. Mixin from this library adds convenient from_dict and to_dict methods to dataclasses:

    from dataclasses import dataclass
    from typing import List
    from mashumaro import DataClassDictMixin
    
    @dataclass
    class Point(DataClassDictMixin):
         x: int
         y: int
    
    @dataclass
    class C(DataClassDictMixin):
         mylist: List[Point]
    
    p = Point(10, 20)
    tmp = {'x': 10, 'y': 20}
    assert p.to_dict() == tmp
    assert Point.from_dict(tmp) == p
    
    c = C([Point(0, 0), Point(10, 4)])
    tmp = {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}
    assert c.to_dict() == tmp
    assert C.from_dict(tmp) == c
    
    0 讨论(0)
  • 2020-12-23 00:23

    Using no additional modules, you can make use of the __post_init__ function to automatically convert the dict values to the correct type. This function is called after __init__.

    from dataclasses import dataclass, asdict
    
    
    @dataclass
    class Bar:
        fee: str
        far: str
    
    @dataclass
    class Foo:
        bar: Bar
    
        def __post_init__(self):
            if isinstance(self.bar, dict):
                self.bar = Bar(**self.bar)
    
    foo = Foo(bar=Bar(fee="La", far="So"))
    
    d= asdict(foo)
    print(d)  # {'bar': {'fee': 'La', 'far': 'So'}}
    o = Foo(**d)
    print(o)  # Foo(bar=Bar(fee='La', far='So'))
    

    This solution has the added benefit of being able to use non-dataclass objects. As long as its str function can be converted back, it's fair game. For example, it can be used to keep str fields as IP4Address internally.

    0 讨论(0)
提交回复
热议问题