将多个类序列化为JSON

3

我有一个类A,其中存储了类型为B的多个变量集合,如何正确地将类A序列化为JSON?

示例:

class A:
    def __init__(self):
        self.b_collection = []
    #...

class B:
    def __init__(self):
        # ...
        pass

并将B的实例添加到集合中:
a = A()
a.b_collection = [B(), B(), B()]

当我尝试使用json.dumps(a)a进行序列化时,我会得到这个错误:Object of type A is not JSON serializable

是否有一种方法可以指定编码器应如何对该类进行编码?

例如:

def __encode__(self, encoder):
    encoder.start_obj()
    encoder.add_property('name', self.value)
    encoder.add_property('age', self.age)
    encoder.end_obj()

这将返回类似于的内容
{
   name: 'Tomer',
   age: '19'
}

你是如何尝试序列化 a 的?使用 json.dumps(a) 吗? - chepner
@chepner 是的,抱歉忘了提到它。 - Tomergt45
2个回答

4
你可以扩展 json.JSONEncoder 来定义如何序列化你的对象。你的子类的 default 方法将会接收一个 Python 对象作为参数。你可以返回一个新对象,该对象可以被编码(希望如此),或将该对象传递给父级以期它知道如何对对象进行编码。
例如:
class A:
    def __init__(self):
        self.b_collection = []

class B:
    def __init__(self, name, age):
        self.name = name
        self.age = age


class ABEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, A):
            return {'__A__': obj.b_collection}
        elif isinstance(obj, B):
            return {'__B__': obj.__dict__}
        return super().default(obj)


a = A()
a.b_collection.append(B("Tomer", "19"))
a.b_collection.append(B("Bob", "21"))
a.b_collection.append(B("Alice", "23"))
print(json.dumps(a, cls=ABEncoder, indent=4))

将产生

{
    "__A__": [
        {
            "__B__": {
                "name": "Tomer",
                "age": "19"
            }
        },
        {
            "__B__": {
                "name": "Bob",
                "age": "21"
            }
        },
        {
            "__B__": {
                "name": "Alice",
                "age": "23"
            }
        }
    ]
}

请注意,你可以分别处理AB;在返回可编码的A形式之前,不必先对B对象进行编码;当列表本身被编码时,B对象将稍后进行编码。
额外的对象使得编写解码器更加容易;如果您不想将JSON解码为A的实例,则无需使其变得如此复杂。相反,您只需定义
class ABEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, A):
            return obj.b_collection
        elif isinstance(obj, B):
            return obj.__dict__
        return super().default(obj)

获取

[
    {
        "name": "Tomer",
        "age": "19"
    },
    {
        "name": "Bob",
        "age": "21"
    },
    {
        "name": "Alice",
        "age": "23"
    }
]
    

0

也许数据类可以帮助解决问题:

from dataclasses import asdict, dataclass
from typing import List
import json


@dataclass
class Person:
    name: str
    age: str


@dataclass
class Group:
    persons: List[Person]


data = [
    {'name': 'Tomer', 'age': '19'},
    {'name': 'Ivan', 'age': '20'}
]
persons = [Person(**person) for person in data]

group = Group(persons=persons)
assert json.dumps(asdict(group)) == '{"persons": [{"name": "Tomer", "age": "19"}, {"name": "Ivan", "age": "20"}]}'

persons = [asdict(person) for person in group.persons]
assert persons == [{"name": "Tomer", "age": "19"}, {"name": "Ivan", "age": "20"}]
assert json.dumps(persons) == '[{"name": "Tomer", "age": "19"}, {"name": "Ivan", "age": "20"}]'


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接