如何在python中将嵌套对象转换为嵌套字典

时间:2020-09-15 01:35:32

标签: python dictionary pydantic

我有一个对象Traceback (most recent call last): File ".import.py", line 17, in <module> modules.append(importlib.import_module(auto,Package=enum)) ,其ID,scene_info和rating等字段如下。可以看出,对象具有属于其他类EntryScene的类型的属性。我想将此对象转换为字典。

Item

Entry(id=None, scene_info=Scene(Recipes=[Item(ID='rec.chicky-nuggies', SpawnerIdx=0), Item(ID='rec.impossible-burger', SpawnerIdx=1)], Decor=[Item(ID='dec.plate-large-orange', SpawnerIdx=2), Item(ID='dec.plate-small-green', SpawnerIdx=3)]), rating=None) (Pdb) vars(self) {'id': None, 'scene_info': Scene(Recipes=[Item(ID='rec.chicky-nuggies', SpawnerIndex=0), Item(ID='rec.impossible-burger', SpawnerIdx=1)], Decor=[Item(ID='dec.plate-large-orange', SpawnerIdx=2), Item(ID='dec.plate-small-green', SpawnerIdx=3)]), 'rating': None}

EXPECTED RESULT

我尝试了{'id': None, 'scene_info':{'Recipes': [{'ID': 'rec.chicky-nuggies', 'SpawnerIdx': 0}, {'ID': 'rec.impossible-burger', 'SpawnerIdx': 1}], 'Decor': [{'ID': 'dec.plate-large-orange', 'SpawnerIndex': 2}, {'ID': 'dec.plate-small-green', 'SpawnerIdx': 3}]}, 'rating': None} ,他们只将外部对象转换为dict,而不将内部对象转换为dict。如何转换嵌套的?

3 个答案:

答案 0 :(得分:0)

我通常这样做:

class Bar:
    # child class
    # some init code...

    def encode(self):
        return vars(self)

class Foo:
    # parent class
    # some init code...

    def encode(self):
        return vars(self)

    def to_json(self, indent=None):
        return json.dumps(self, default=lambda o: o.encode(), indent=indent)

to_json()将为您提供该类及其嵌套对象的json字符串(如果它们足够简单),您也可以使用棉花糖通过更多控制来做到这一点。您可以只在父类中执行return json.dumps(self, default=lambda o: vars(o), indent=indent),而没有encode()方法,但是使用encode方法可以自定义输出。

下面是一些随机的,愚蠢的代码,以显示其用法和输出:

import json


class Ingredient:
    def __init__(self, name, cost=0):
        self.name = name
        self.cost = cost

    def encode(self):
        return vars(self)


class Recipe:
    def __init__(self, name, prep_time=0, cook_time=0, ingredients=None,
                 instructions=None):
        self.name = name
        self.prep_time = prep_time
        self.cook_time = cook_time
        self.ingredients = ingredients or []
        self.instructions = instructions or {}

    def encode(self):
        return vars(self)

    def to_json(self, indent=None):
        return json.dumps(self, default=lambda o: o.encode(), indent=indent)


lettuce = Ingredient('Lettuce', 1.3)
tomato = Ingredient('Tomato', 5.2)

salad = Recipe('Salad', prep_time=5, cook_time=0)

salad.ingredients = [
    lettuce,
    tomato
]

salad.instructions = {
    'Step 1': 'Get the ingredients out',
    'Step 2': 'Mix tem together',
    'Step 3': 'Eat' 
}

print(salad.to_json(4))

输出:

{
    "name": "Salad",
    "prep_time": 5,
    "cook_time": 0,
    "ingredients": [
        {
            "name": "Lettuce",
            "cost": 1.3
        },
        {
            "name": "Tomato",
            "cost": 5.2
        }
    ],
    "instructions": {
        "Step 1": "Get the ingredients out",
        "Step 2": "Mix tem together",
        "Step 3": "Eat"
    }
}

答案 1 :(得分:0)

对于类类型(Entry \ Scene \ Item),您可以创建一个函数,该函数以字典形式返回参数。

尝试以下代码:

def getargs(**kwargs):
   return kwargs  # already a dictionary

Entry = Scene = Item = getargs  # all functions do same thing

x = Entry(id=None, scene_info=Scene(Recipes=[Item(ID='rec.chicky-nuggies', SpawnerIdx=0), Item(ID='rec.impossible-burger', SpawnerIdx=1)], Decor=[Item(ID='dec.plate-large-orange', SpawnerIdx=2), Item(ID='dec.plate-small-green', SpawnerIdx=3)]), rating=None)

print(x)

输出

{'id': None, 'scene_info': {'Recipes': [{'ID': 'rec.chicky-nuggies', 'SpawnerIdx': 0}, {'ID': 'rec.impossible-burger', 'SpawnerIdx': 1}], 'Decor': [{'ID': 'dec.plate-large-orange', 'SpawnerIdx': 2}, {'ID': 'dec.plate-small-green', 'SpawnerIdx': 3}]}, 'rating': None}

答案 2 :(得分:0)

首选的方法是使用Tenacious B所述的修饰类定义,但是如果您想要一种快速的解决方案,则可以使用下面所述的 recursive 函数。

def class2dict(instance, built_dict={}):
    if not hasattr(instance, "__dict__"):
        return instance
    new_subdic = vars(instance)
    for key, value in new_subdic.items():
        new_subdic[key] = class2dict(value)
    return new_subdic

示例:

# Class definitions
class Scene:
    def __init__(self, time_dur, tag):
        self.time_dur = time_dur
        self.tag = tag


class Movie:
    def __init__(self, scene1, scene2):
        self.scene1 = scene1
        self.scene2 = scene2


class Entry:
    def __init__(self, movie):
        self.movie = movie
In [2]: entry = Entry(Movie(Scene('1 minute', 'action'), Scene('2 hours', 'comedy')))                                                                                                                                                                                       
In [3]: class2dict(entry)                                                                                                             
Out[3]:                                                                                                                          
{'movie': {
    'scene1': {'time_dur': '1 minute', 'tag': 'action'},                                                                         
    'scene2': {'time_dur': '2 hours', 'tag': 'comedy'}}
}