dataclass from dict with differing key names

Viewed 138

Is it possible to translate keys to class properties in dataclasses? The reason is that the keys in the dict (which I cut out from a JSON file) does not have matching attribute names in JSON (e.g. _id in the below example has to become id).

With the code below I feel like I'm writing too much boilerplate.

Dict:

{'_id': '5719fdf6edf5136d37aaf562', 'divespot': 'The Tugs', 'divesite': 'Fathom Five National Park', 'region': 'Ontario', 'country': 'Canada'}

class:

class DiveSpot:
    id: str
    name: str

    def from_dict(self, divespot):
        self.id = divespot.get("_id")
        self.name = divespot.get("divespot")
2 Answers
from dataclasses import dataclass

dskeymap = {'_id': 'id', 'divespot': 'name', 'divesite': 'site', 'region': 'region', 'country': 'country'}
data =  {'_id': '5719fdf6edf5136d37aaf562', 'divespot': 'The Tugs', 'divesite': 'Fathom Five National Park', 
    'region': 'Ontario', 'country': 'Canada'}

@dataclass
class DiveSpot:
    id: str
    name: str
    site: str
    region: str
    country: str

ds = DiveSpot(**{newk: data[oldk] for oldk, newk in dskeymap.items()})

Printing ds gives

DiveSpot(id='5719fdf6edf5136d37aaf562', name='The Tugs', site='Fathom Five National Park', region='Ontario', country='Canada')

Or add a @classmethod

@dataclass
class DiveSpot:
    id: str
    name: str
    site: str
    region: str
    country: str

    @classmethod
    def fromdict(cls, d, keymap=dskeymap):
        return cls(**{newk: data[oldk] for oldk, newk in dskeymap.items()})

You can first transform the dictionary before creating the dataclass, for example:

divespot_dict = dict(divespot)
divespot_copy['id'] = divespot_dict['_id']
divespot = DiveSpot(**divespot_copy)
Related