如何使 dict 子类 json 可序列化?
How do I make a dict subclass json serializable?
我可以用 json.dumps
表示我的 Simple_Dict_Subclass
和 List_Subclass
,但不能 Custom_Dict_Subclass
。当在 List_Subclass
上调用 json.dumps
时,它的 __iter__
方法被调用,所以我推断 json.dumps
会调用字典的 items
方法。 items
在 Simple_Dict_Subclass
中调用,但在 Custom_Dict_Subclass
中未调用。如何使我的 Custom_Dict_Subclass
json
像 Simple_Dict_Subclass
一样可序列化?
import json
class Custom_Dict_Subclass(dict):
def __init__(self):
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
def __getitem__(self, key):
return self.data[key]
def __str__(self):
return str(self.data)
def items(self):
print("'Items' called from Custom_Dict_Subclass")
yield from self.data.items()
class Simple_Dict_Subclass(dict):
def __setitem__(self, key, value):
super().__setitem__(key, value)
def __getitem__(self, key):
return super().__getitem__(key)
def __str__(self):
return super().__str__()
def items(self):
print("'Items' called from Simple_Dict_Subclass")
yield from super().items()
class List_Subclass(list):
def __init__(self):
self.data = []
def __setitem__(self, index, value):
self.data[index] = value
def __getitem__(self, index):
return self.data[index]
def __str__(self):
return str(self.data)
def __iter__(self):
yield from self.data
def append(self, value):
self.data.append(value)
d = Custom_Dict_Subclass()
d[0] = None
print(d) # Works
print(json.dumps(d)) # Does't work
d = Simple_Dict_Subclass()
d[0] = None
print(d) # Works
print(json.dumps(d)) # Works
l = List_Subclass()
l.append(None)
print(l) # Works
print(json.dumps(l)) # Works
输出:
{0: None} # Custom dict string working
{} # Custom dict json.dumps not working
{0: None} # Simple dict string working
'Items' called from Simple_Dict_Subclass
{"0": null} # Simple dict json.dumps working
[None] # List string working
[null] # List json.dumps working
一般来说,假设 json.dumps
会
触发字典的 items
方法。事情是这样的
已实施,但您不能依赖它。
在你的例子中,Custom_Dict_Subclass.items
永远不会被调用,因为
(key, value) 对不会添加到 dict
对象,而是添加到它的
data
属性。
要解决这个问题,您需要在
Custom_Dict_Subclass
:
class Custom_Dict_Subclass(dict):
def __init__(self):
dict.__init__(self)
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
super().__setitem__(key, value)
对象被正确转储,当然,(key, value) 将随后
被存储两次:在 dict
对象和它的 data
属性中。
在那种情况下,最好定义一个子 class
json.JSONEncoder
执行翻译一个
Custom_Dict_Subclass
对象到 json 可序列化对象和
将此 class 作为关键字参数 cls
of json.dumps
:
import json
class Custom_Dict_Subclass:
def __init__(self):
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
def __getitem__(self, key):
return self.data[key]
def __str__(self):
return str(self.data)
def items(self):
print("'Items' called from Custom_Dict_Subclass")
yield from self.data.items()
class CustomDictEncoder(json.JSONEncoder):
def default(self, obj):
"""called by json.dumps to translate an object obj to
a json serialisable data"""
if isinstance(obj, Custom_Dict_Subclass):
return obj.data
return json.JSONEncoder.default(self, obj)
d = Custom_Dict_Subclass()
d[0] = None
print(json.dumps(d, cls=CustomDictEncoder))
我可以用 json.dumps
表示我的 Simple_Dict_Subclass
和 List_Subclass
,但不能 Custom_Dict_Subclass
。当在 List_Subclass
上调用 json.dumps
时,它的 __iter__
方法被调用,所以我推断 json.dumps
会调用字典的 items
方法。 items
在 Simple_Dict_Subclass
中调用,但在 Custom_Dict_Subclass
中未调用。如何使我的 Custom_Dict_Subclass
json
像 Simple_Dict_Subclass
一样可序列化?
import json
class Custom_Dict_Subclass(dict):
def __init__(self):
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
def __getitem__(self, key):
return self.data[key]
def __str__(self):
return str(self.data)
def items(self):
print("'Items' called from Custom_Dict_Subclass")
yield from self.data.items()
class Simple_Dict_Subclass(dict):
def __setitem__(self, key, value):
super().__setitem__(key, value)
def __getitem__(self, key):
return super().__getitem__(key)
def __str__(self):
return super().__str__()
def items(self):
print("'Items' called from Simple_Dict_Subclass")
yield from super().items()
class List_Subclass(list):
def __init__(self):
self.data = []
def __setitem__(self, index, value):
self.data[index] = value
def __getitem__(self, index):
return self.data[index]
def __str__(self):
return str(self.data)
def __iter__(self):
yield from self.data
def append(self, value):
self.data.append(value)
d = Custom_Dict_Subclass()
d[0] = None
print(d) # Works
print(json.dumps(d)) # Does't work
d = Simple_Dict_Subclass()
d[0] = None
print(d) # Works
print(json.dumps(d)) # Works
l = List_Subclass()
l.append(None)
print(l) # Works
print(json.dumps(l)) # Works
输出:
{0: None} # Custom dict string working
{} # Custom dict json.dumps not working
{0: None} # Simple dict string working
'Items' called from Simple_Dict_Subclass
{"0": null} # Simple dict json.dumps working
[None] # List string working
[null] # List json.dumps working
一般来说,假设 json.dumps
会
触发字典的 items
方法。事情是这样的
已实施,但您不能依赖它。
在你的例子中,Custom_Dict_Subclass.items
永远不会被调用,因为
(key, value) 对不会添加到 dict
对象,而是添加到它的
data
属性。
要解决这个问题,您需要在
Custom_Dict_Subclass
:
class Custom_Dict_Subclass(dict):
def __init__(self):
dict.__init__(self)
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
super().__setitem__(key, value)
对象被正确转储,当然,(key, value) 将随后
被存储两次:在 dict
对象和它的 data
属性中。
在那种情况下,最好定义一个子 class
json.JSONEncoder
执行翻译一个
Custom_Dict_Subclass
对象到 json 可序列化对象和
将此 class 作为关键字参数 cls
of json.dumps
:
import json
class Custom_Dict_Subclass:
def __init__(self):
self.data = {}
def __setitem__(self, key, value):
self.data[key] = value
def __getitem__(self, key):
return self.data[key]
def __str__(self):
return str(self.data)
def items(self):
print("'Items' called from Custom_Dict_Subclass")
yield from self.data.items()
class CustomDictEncoder(json.JSONEncoder):
def default(self, obj):
"""called by json.dumps to translate an object obj to
a json serialisable data"""
if isinstance(obj, Custom_Dict_Subclass):
return obj.data
return json.JSONEncoder.default(self, obj)
d = Custom_Dict_Subclass()
d[0] = None
print(json.dumps(d, cls=CustomDictEncoder))