Consider this json file named h.json
I want to convert this into a python dataclass.
{ "acc1":{ "email":"acc1@example.com", "password":"acc1", "name":"ACC1", "salary":1 }, "acc2":{ "email":"acc2@example.com", "password":"acc2", "name":"ACC2", "salary":2 } }
I could use an alternative constructor for getting each account, for example:
import json from dataclasses import dataclass @dataclass class Account(object): email:str password:str name:str salary:int @classmethod def from_json(cls, json_key): file = json.load(open("h.json")) return cls(**file[json_key])
but this is limited to what arguments (email, name, etc.) were defined in the dataclass.
What if I were to modify the json to include another thing, say age?
The script would end up returning a TypeError
, specifically TypeError: __init__() got an unexpected keyword argument 'age'
.
Is there a way to dynamically adjust the class attributes based on the keys of the dict (json object), so that I don’t have to add attributes each time I add a new key to the json?
Advertisement
Answer
This way you lose some dataclass
features.
- Such as determining whether it is
optional
or not - Such as auto-completion feature
However, you are more familiar with your project and decide accordingly
There must be many methods, but this is one of them:
@dataclass class Account(object): email: str password: str name: str salary: int @classmethod def from_json(cls, json_key): file = json.load(open("1.txt")) keys = [f.name for f in fields(cls)] # or: keys = cls.__dataclass_fields__.keys() json_data = file[json_key] normal_json_data = {key: json_data[key] for key in json_data if key in keys} anormal_json_data = {key: json_data[key] for key in json_data if key not in keys} tmp = cls(**normal_json_data) for anormal_key in anormal_json_data: setattr(tmp,anormal_key,anormal_json_data[anormal_key]) return tmp test = Account.from_json("acc1") print(test.age)