konradhalas / dacite

Simple creation of data classes from dictionaries.
MIT License
1.76k stars 106 forks source link

Mapping key names to class attributes #232

Open Mettwasser opened 1 year ago

Mettwasser commented 1 year ago

I get frustrated when I get (for example) responses from an API which are camelCase. My question is: is there already a way to map the classes' fields to the response's names

say, the response dict contains a "fullName" key. I would like to be able to just map it to a "full_name" attribute, without having to change the key myself (which is the only solution I found)

Is there a way to do this? If so, please ignore this, and PLEASE tell me. Browsed through half the internet but I wasn't able to find anything.

It also becomes a problem when the response contains something like "from" as key.

Solution (?) A similiar approach to SQLAlchemy's ORM would maybe fit this. Something like full_name: str = dacite.Map("fullName")

An alternative is possibly a decorator when creating the dataclass for mapping, takes in a dict, so you could e.g. pass it {"fullName": "full_name"}

Again, there might be a way, it's just I haven't found anything. Just wanted to make sure that someone recommended this.

Mettwasser commented 1 year ago

this can work:

def translate_keys(mapping: Dict[str, str]):
    def inner(cls: Type):
        original_func: Callable = cls._from_response

        def override(cls: Type, data: Dict[str, str]):
            for key in mapping.keys():
                if key in data:
                    data[mapping[key]] = data.pop(key)

            return original_func(data)

        setattr(cls, "_from_response", classmethod(override))

        return cls

    return inner

Kinda specific but it gets the job done, dunno if I should close this

mkuijn-cb commented 1 year ago

I've got JSON objects with attributes called "from". This is a basic function that's missing. We need something similar to the JsonProperty annotation in Jackson (Java)