Im trying to write a custom Json encoder for an existing Datastructure. It contains a List of Containers with names, values and descriptions. The List needs to be transformed to a Dictionary before its turned into JSON. Because the Container may also contain a list of containers I wanted to use the JSON encoders recursive behaviour to make it simpler. However I'm unable to make my encoder go into the list case.
我正在尝试为现有的数据结构编写一个定制的Json编码器。它包含一个容器列表,其中包含名称、值和描述。在将列表转换为JSON之前,需要将其转换为字典。因为Container可能还包含一个容器列表,所以我想使用JSON编码器的递归行为来使其更简单。然而,我无法让我的编码器进入列表情况。
import json
from functools import reduce
class ContainerEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, list):
if reduce(lambda a, b: a and isinstance(b, Container), obj, True):
return {x.get_name(): {"prop": x.get_prop(), "desc": x.get_desc()} for x in ContainerStore}
else:
return json.JSONEncoder.default(self, obj)
if isinstance(obj, Container):
return {obj.get_name(): {"prop": obj.get_prop(), "desc": obj.get_desc()}}
return json.JSONEncoder.default(self, obj)
class Container:
def __init__(self, name: str, prop: any = None, desc: str = ""):
self._name = name
self._prop = prop
self._desc = desc
def get_name(self):
return self._name
def get_prop(self):
return self._prop
def get_desc(self):
return self._desc
C1 = Container("Container1", 12, "Container Holding a Number")
C2 = Container("Container2", True, "Container Holding a Boolean Value")
C3 = Container("CoolContainer", [1, 2, 3, 4], "Container Holding a List")
ContainerStore = [C1, C2, C3]
ContainerDict = {x.get_name(): {"prop": x.get_prop(), "desc": x.get_desc()} for x in ContainerStore}
dump1 = json.dumps(ContainerStore, cls=ContainerEncoder)
print(dump1)
dump2 = json.dumps(ContainerDict)
print(dump2)
The problem seems to be that isinstance(obj, list) never returns true and so it always uses the Standard Encoder to encode the List and then encodes all the containers individually.
问题似乎是isInstance(obj,list)永远不会返回TRUE,所以它总是使用标准编码器来编码列表,然后分别编码所有容器。
print(isinstance(ContainerStore, list))
is True so it should work but I'm pretty new to Python so any help is appreciated
print(isinstance(ContainerStore,list))是True,所以它应该可以工作,但我对Python很陌生,所以任何帮助都很感激
更多回答
I believe the default()
method is only called for object types that the encoder doesn't know how to handle. So your custom method is called for the contents of the list, but not for the list object itself.
我相信只有编码者不知道如何处理的对象类型才会调用Default()方法。因此,您的定制方法是为列表内容调用的,而不是为列表对象本身调用的。
In this context, obj
is always going to be of type Container
because that is what the JSON module passes to your encoder. Instead of isinstance(obj, list)
try using isinstance(obj.get_prop(), list)
to test the instance of the property.
在这种情况下,obj将始终是Container类型,因为这是JSON模块传递给编码器的类型。尝试使用isInstance(obj.get_prop(),list)来测试该属性的实例,而不是使用isInstance(obj,list)。
更多回答
我是一名优秀的程序员,十分优秀!