I'm trying to create a custom constructor for my python dataclass that will ideally take in a dict (from request json data) and fill in the attributes of the dataclass.
Eg
@dataclass
class SoldItem:
title: str
purchase_price: float
shipping_price: float
order_data: datetime
def main():
json = requests.get(URL).json()
sold_item = SoldItem(json)
So I want SoldItem to have a method that saves the json data in the appropriate attributes of the dataclass instead of having to do SoldItem(title=json['title']...
I would also preferably have the class be able to recognise that the data being passed in is a dict and execute the from dict constructor.
I have done my best to look up possible solutions but have come up mostly empty.
Any help would be greatly appreciated.
For the simplest approach - with no additional libraries - I would personally go with a de-structuring approach via **kwargs
.
For example:
>>> json = {'title': 'test', 'purchase_price': 1.2, 'shipping_price': 42, 'order_data': datetime.min}
>>> SoldItem(**json)
SoldItem(title='test', purchase_price=1.2, shipping_price=42, order_data=datetime.datetime(1, 1, 1, 0, 0))
In case of a more involved use case, such as:
snake_case
In such cases, I would suggest third-party tools that will automagically handle this data transform for you.
For instance, the dataclass-wizard
is a (de)serialization library I have come up with, for exactly this use case, i.e. when the input data might be coming from another source, such as the result of an API call or response.
It can be installed with pip
:
pip install dataclass-wizard
Usage:
from dataclasses import dataclass
from datetime import datetime
from dataclass_wizard import JSONWizard
@dataclass
class SoldItem(JSONWizard):
title: str
purchase_price: float
shipping_price: float
order_data: datetime
def main():
from pprint import pprint
# json = requests.get(URL).json()
json = {'title': 'test',
'purchasePrice': '1.23',
'shipping-price': 42,
'Order_Data': '2021-01-02T12:34:56Z'}
# create a `SoldItem` instance from an input `dict`,
# such as from an API response.
sold_item = SoldItem.from_dict(json)
pprint(sold_item)
if __name__ == '__main__':
main()
Prints:
SoldItem(title='test',
purchase_price=1.23,
shipping_price=42.0,
order_data=datetime.datetime(2021, 1, 2, 12, 34, 56, tzinfo=datetime.timezone.utc))