Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

cattrs : can I use a json converter in a class method to instantiate an object from a json file?

I have been an extensive user of attrs for two years, but I have discovered cattrs only recently so my question may sound naive.

In my codes, I often use a class method to instantiate an attrs object from a json file. For example :

from cattrs.preconf.json import make_converter
from attrs import field, define, validators

from enum import StrEnum, auto
from pathlib import Path

class Colors(StrEnum):
    BLUE = auto()
    RED = auto()
    GREEN = auto()


@define
class A:
    color: Colors = field(validator=validators.instance_of(Colors))
    value: int = field(validator=validators.instance_of(int))

    @classmethod
    def from_json_file(cls, path: Path):
        with open(path, 'r') as f:
            data = json.load(f)
        return cls(color=Colors(data["color"]), value=data["value"])

I was wondering if I could use the power of ¢attrs and the json converter in the following way :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    @classmethod
    def from_json_file(cls, path: Path):
        json_converter = make_converter()
        return json_converter.loads(path.read_text(), cls)

The code works as expected but does it respect the principle of cattrs to separate the class logic from the un/structuring rules ?

>Solution :

No. Creating a converter instance within the class method violates cattrs’ principle of separation between class logic and un/structuring rules. The conversion configuration should be maintained externally.

converter = make_converter()
converter.register_structure_hook(Colors, lambda v, _: Colors(v))

@define
class A:
    color: Colors = field(validator=validators.instance_of(Colors))
    value: int = field(validator=validators.instance_of(int))

def load_a_from_json(path: Path) -> A:
    return converter.loads(path.read_text(), A)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading