python - 无法在自定义编码器中将字典编码为 JSON

标签 python json

我正在尝试制作一个自定义 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/

相关文章:

python - 在 python 中使用 'finally' 子句的范围是什么?

python - 属性错误 : 'Timestamp' object has no attribute 'timestamp

jquery - 代码未循环遍历整个 json 数据

javascript - 按键名过滤 JSON 数据

python - 如果 json 中存在可选键,则 Django 过滤器

python - 为什么我不能在 Crontab 中使用 Python 3?

python - Pycharm jupyter单元格背景

python - 使用 rtsp 流时 Tensorflow 对象检测速度慢

javascript - 如何在 React Native ListView 中过滤和呈现重复出现的嵌套 JSON 数据?

java - Json 嵌套对象检查是否为 null