I'd like to make a class which can convert class to dictionary or json directly with sizable list object
I'm using this dictionary uploading mongodb data
I found a way multi layer dictionary converting, using dict() by overriding using __iter__ object
###############################################################
# __iter__ override
class Singleton(type):
def __iter__(self):
for attr1_name in dir(self):
attr1 = getattr(self, attr1_name)
if not "__" in attr1_name:
if callable(attr1):
for attr2_name in dir(attr1):
if not "__" in attr2_name:
attr2 = getattr(attr1, attr2_name)
yield (attr1_name, dict(attr1))
else:
yield (attr1_name, attr1)
################################################################
# data structure
class OrderItem(metaclass=Singleton):
ridx = -1
tray = -1
batter = -1
fry = -1
class Data(metaclass=Singleton):
request_id = 0
order_id = "random_str"
items = OrderItem
items2 = list(OrderItem)
def __init__(self) -> None:
self.items2.append(OrderItem)
self.items2.append(OrderItem)
class Order(metaclass=Singleton):
key = ""
command = "order"
data = Data
o = Order
d = dict(o)
print(d)
This return
{'command': 'order', 'data': {'items': {'batter': -1, 'fry': -1, 'ridx': -1, 'tray': -1}, 'items2': [('batter', -1), ('fry', -1), ('ridx', -1), ('tray', -1)], 'order_id': 'random_str', 'request_id': 0}, 'key': ''}
I want items value is list of OrderItem class. like this
{"command": "order", "data": {"items": [{"batter": -1, "fry": -1, "ridx": -1, "tray": -1}, {"batter": -1, "fry": -1, "ridx": -1, "tray": -1}], "order_id": "random_str", "request_id": 0}, "key": ""}
Is there any way to dict() output like this?
Or other ways of converting class object to multilayer list dictionary
CodePudding user response:
How about using @dataclass
and as dict
from dataclasses
:
from dataclasses import dataclass, field, as_dict
@dataclass
class OrderItem(metaclass=Singleton):
ridx = -1
tray = -1
batter = -1
fry = -1
@dataclass
class Data(metaclass=Singleton):
request_id = 0
order_id = "random_str"
items : list[OrderItem] = field(default_factory=list)
def __init__(self) -> None:
self.items2.append(OrderItem())
@dataclass
class Order(metaclass=Singleton):
key = ""
command = "order"
data = Data
o = Order
print(as_dict(o))
CodePudding user response:
Answer summary
from dataclasses import dataclass, field, asdict, astuple
from dacite import from_dict
from typing import List
@dataclass
class OrderItem:
ridx: int = -1
tray: int = -1
batter: int = -1
fry: int = -1
@dataclass
class Data:
request_id: int = -1
order_id: str = ""
items: List[OrderItem] = field(default_factory=list)
@dataclass
class Order:
key : str = ""
command: str = "order"
data: Data = field(default_factory=object)
items = [OrderItem (0,0,2,3), OrderItem (0,0,1,2), OrderItem (0,0,1,1), OrderItem(0,0,0,0)]
data = Data(0, "oid2920", items)
order = Order("order_key", "order", data)
dict = asdict(order)
print(dict)
print()
order_copy = from_dict(Order, dict)
dict = asdict(order_copy)
print(dict)
print()