问题描述
我有一个对象Traceback (most recent call last):
File ".import.py",line 17,in <module>
modules.append(importlib.import_module(auto,Package=enum))
,其ID,scene_info和rating等字段如下。可以看出,对象具有属于其他类Entry
和Scene
的类型的属性。我想将此对象转换为字典。
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),'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。如何转换嵌套的?
解决方法
我通常这样做:
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,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=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"
}
}
,
对于类类型(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}
,
首选的方法是使用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'}}
}