我试图用JSON(使用simplejson)序列化python对象列表,但得到的错误是该对象"不可JSON序列化".

The class is a simple class having fields that are only integers, strings, and floats, and inherits similar fields from one parent superclass, e.g.:

class ParentClass:
  def __init__(self, foo):
     self.foo = foo

class ChildClass(ParentClass):
  def __init__(self, foo, bar):
     ParentClass.__init__(self, foo)
     self.bar = bar

bar1 = ChildClass(my_foo, my_bar)
bar2 = ChildClass(my_foo, my_bar)
my_list_of_objects = [bar1, bar2]
simplejson.dump(my_list_of_objects, my_filename)

where foo, bar are simple types like I mentioned above. The only tricky thing is that ChildClass sometimes has a field that refers to another object (of a type that is not ParentClass or ChildClass).

What is the easiest way to serialize this as a json object with simplejson? Is it sufficient to make it serializable as a dictionary? Is the best way to simply write a dict method for ChildClass? Finally, does having the field that refer to another object significantly complicate things? If so, I can rewrite my code to only have simple fields in classes (like strings/floats etc.)

thank you.

推荐答案

I've used this strategy in the past and been pretty happy with it: Encode your custom objects as JSON object literals (like Python dicts) with the following structure:

{ '__ClassName__': { ... } }

这实质上是一个单项dict,其单个键是指定编码对象类型的特殊字符串,其值是实例属性的dict.如果这有道理的话.

编码器和解码器的一个非常简单的实现(简化self 实际使用的代码)如下所示:

TYPES = { 'ParentClass': ParentClass,
          'ChildClass': ChildClass }


class CustomTypeEncoder(json.JSONEncoder):
    """A custom JSONEncoder class that knows how to encode core custom
    objects.

    Custom objects are encoded as JSON object literals (ie, dicts) with
    one key, '__TypeName__' where 'TypeName' is the actual name of the
    type to which the object belongs.  That single key maps to another
    object literal which is just the __dict__ of the object encoded."""

    def default(self, obj):
        if isinstance(obj, TYPES.values()):
            key = '__%s__' % obj.__class__.__name__
            return { key: obj.__dict__ }
        return json.JSONEncoder.default(self, obj)


def CustomTypeDecoder(dct):
    if len(dct) == 1:
        type_name, value = dct.items()[0]
        type_name = type_name.strip('_')
        if type_name in TYPES:
            return TYPES[type_name].from_dict(value)
    return dct

在这个实现中,假设您正在编码的对象将有一个from_dict()类的方法,该方法知道如何从从JSON解码的dict中重新创建实例.

It's easy to expand the encoder and decoder to support custom types (e.g. datetime objects).

EDIT,回答您的编辑:这样一个实现的好处是,它将自动编码和解码在TYPES映射中找到的任何对象的实例.这意味着它将自动处理这样的子类:

class ChildClass(object):
    def __init__(self):
        self.foo = 'foo'
        self.bar = 1.1
        self.parent = ParentClass(1)

That should result in JSON something like the following:

{ '__ChildClass__': {
    'bar': 1.1,
    'foo': 'foo',
    'parent': {
        '__ParentClass__': {
            'foo': 1}
        }
    }
}

Json相关问答推荐

将json数组反序列化为选项 struct

将JSON输入子数组转换为字符串顺序列表输出

如何使用JQ打印每个根级对象键一行?

集成wix.comstore API|变音符号问题

如何使用模式注册中心创建从主题中取消本地化的ks qlDB表?

使用Kotlin限制序列化类属性的允许整数值

在深度嵌套数组中使用布尔属性的jq-select

Jolt:数组中两个字符串的连接

Ansible - 将文件内容添加到字典中

如何使用SQLite Trigger将JSON对象数组转换为新记录?

如何在 jq 中按 IP 地址排序?

如何修复通过在 tsconfig.json 文件中添加allowImportingTsExtensions引发的错误 TS5023?

每次在 SoapUI 中发送请求时,将 JSON 响应的子 node 分配给项目变量

为什么解析的字典相等而腌制的字典不相等?

解析 JSON API 响应

在 JSON 反序列化期间没有为System.String类型定义无参数构造函数

ASP.NET MVC 读取原始 JSON 发布数据

waitUntilAllTask​​sAreFinished 错误 Swift

Gson 将一组数据对象转换为 json - Android

春天:返回@ResponseBodyResponseEntity>