我正在尝试制作一个自定义 JSON 编码器,但遇到了这个我不明白的问题。
我基本上按照official documentation的说明进行操作
使用标准 JSON 编码器显然可以对字典进行编码。但是,如果我将自定义对象转换为 dict 并将其传递给默认编码器,我会得到一个:TypeError: Object of type dict is not JSON Serialized
。
显然我在这里缺少一些东西。有人可以向我解释下面的玩具示例的行为吗?
import json
class Klass():
def __init__(self,number):
self.number = number
def __dict__(self):
return {"number": self.number}
class CustomEncoder(json.JSONEncoder):
def default(self,obj):
if isinstance(obj,Klass):
obj=obj.__dict__()
return json.JSONEncoder.default(self, obj)
json.dumps({"number" : 10}) # works
json.dumps({"number" : 10},cls=json.JSONEncoder) # works
json.dumps({"number" : 10},cls=CustomEncoder) # works
json.dumps(Klass(10).__dict__(), cls=CustomEncoder) # works
json.dumps({"Test":Klass(10).__dict__()}, cls=CustomEncoder) #works
try:
json.dumps(Klass(10), cls=CustomEncoder) # TypeError: Object of type dict is not JSON serializable
except TypeError:
print("Error 1")
# this is my end goal to encode a dict of objects
try:
json.dumps({"Test":Klass(10)}, cls=CustomEncoder) # TypeError: Object of type dict is not JSON serializable
except TypeError:
print("Error 2")
# this works but clearly it shows me the Custom encoder is not doing what I think it does
encode_hack = {k: v.__dict__() for k, v in {"Test":Klass(10)}.items()}
json.dumps(encode_hack)
最佳答案
您不应定义名为 __dict__
的类方法,这是一个special read-only built-in class attribute ,而不是方法,并且您不需要重载即可执行您想要的操作。
这是代码的修改版本,展示了如何执行操作:
import json
class Klass:
def __init__(self,number):
self.number = number
# Don't do this.
# def __dict__(self):
# return {"number": self.number}
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Klass):
# obj=obj.__dict__()
return {"number": obj.number}
return json.JSONEncoder.default(self, obj)
json.dumps({"number" : 10}) # works
json.dumps({"number" : 10}, cls=json.JSONEncoder) # works
json.dumps({"number" : 10}, cls=CustomEncoder) # works
json.dumps(Klass(10).__dict__, cls=CustomEncoder) # works
json.dumps({"Test":Klass(10).__dict__}, cls=CustomEncoder) #works
try:
json.dumps(Klass(10), cls=CustomEncoder)
except TypeError as exc:
print(exc)
# this is my end goal to encode a dict of objects
try:
json.dumps({"Test":Klass(10)}, cls=CustomEncoder)
except TypeError as exc:
print(exc)
# this works but clearly it shows me the Custom encoder is not doing what i think it does
encode_hack = {k: v.__dict__ for k, v in {"Test":Klass(10)}.items()}
json.dumps(encode_hack)
更新
我认为更好的方法是重命名您的 __dict__()
方法到未保留的东西并让您的自定义编码器调用它。一个主要优点是,现在它更加面向对象和通用,因为任何具有该名称的方法的类都可以被编码(并且您不必硬编码类名,例如Klass
在编码器中)。
这就是我的意思:
import json
class Klass:
def __init__(self,number):
self.number = number
def _to_json(self):
return {"number": self.number}
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
try:
return obj._to_json()
except AttributeError:
return super().default(obj)
# A single object.
try:
print(json.dumps(Klass(10), cls=CustomEncoder)) # -> {"number": 10}
except TypeError as exc:
print(exc)
# A dict of them.
try:
print(json.dumps({"Test":Klass(42)}, cls=CustomEncoder)) # -> {"Test": {"number": 42}}
except TypeError as exc:
print(exc)
关于python - 无法在自定义编码器中将字典编码为 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69942871/