Can I covert python class to dictionary or json like Newtonsoft.Json.JsonConvert() in C#

Question:

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

Asked By: labovming

||

Answers:

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))  

Answered By: SystemSigma_

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)

# dataclass to dict
dict = asdict(order)
print(json.dumps(dict, sort_keys=True, indent=4))
print()

# dict to dataclass
order_copy = from_dict(Order, dict)
dict = asdict(order_copy)
print(json.dumps(dict, sort_keys=True, indent=4))
print()

result of data class to dictionary and dictionary to dataclass
converting json for print structure

{
    "command": "order",
    "data": {
        "items": [
            {
                "batter": 2,
                "fry": 3,
                "ridx": 0,
                "tray": 0
            },
            {
                "batter": 1,
                "fry": 2,
                "ridx": 0,
                "tray": 0
            },
            {
                "batter": 1,
                "fry": 1,
                "ridx": 0,
                "tray": 0
            },
            {
                "batter": 0,
                "fry": 0,
                "ridx": 0,
                "tray": 0
            }
        ],
        "order_id": "oid2920",
        "request_id": 0
    },
    "key": "order_key"
}
Answered By: labovming
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.