You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为包含自定义类对象的复杂类编写自定义JSON解码器?

为包含自定义类的Edge类编写JSON解码器

哈哈,我懂你现在的困境——已经搞定了Edge列表的JSON序列化,反序列化却不知道怎么下手对吧?别慌,咱们一步步来解决这个问题,核心思路就是在序列化时给自定义类打上标识,反序列化时根据标识还原对象。

先理清楚前提(假设你的类结构大概是这样)

首先我先基于你描述的场景,还原一下Actor、Movie和Edge类的基本结构(soup属性因为无法序列化,咱们序列化时会忽略它):

from bs4 import BeautifulSoup
import json

class Actor:
    def __init__(self, name, soup: BeautifulSoup):
        self.name = name
        self.soup = soup

class Movie:
    def __init__(self, title, soup: BeautifulSoup):
        self.title = title
        self.soup = soup

class Edge:
    def __init__(self, actor: Actor, movie: Movie):
        self.actor = actor
        self.movie = movie

第一步:回顾你的自定义编码器(确保带类型标识)

你已经写好的编码器,一定要给每个自定义类加上__type__字段,这是解码器识别对象类型的关键。比如你的编码器可以是这样:

class EdgeEncoder(json.JSONEncoder):
    def default(self, obj):
        # 处理Edge对象
        if isinstance(obj, Edge):
            return {
                "__type__": "Edge",
                "actor": self.default(obj.actor),
                "movie": self.default(obj.movie)
            }
        # 处理Actor对象
        elif isinstance(obj, Actor):
            return {
                "__type__": "Actor",
                "name": obj.name
                # soup属性无法序列化,直接忽略,后续可以按需重新获取
            }
        # 处理Movie对象
        elif isinstance(obj, Movie):
            return {
                "__type__": "Movie",
                "title": obj.title
                # 同样忽略soup
            }
        # 其他类型交给父类处理
        return super().default(obj)

第二步:编写自定义解码器(用object_hook更灵活)

反序列化的核心是用json.loads()的object_hook参数,它会在解析每个JSON字典时触发,我们可以根据__type__字段来还原对应的类实例:

def edge_decoder(obj):
    # 先判断是不是Edge类型
    if "__type__" in obj and obj["__type__"] == "Edge":
        # 先还原Actor实例
        actor = edge_decoder(obj["actor"])
        # 再还原Movie实例
        movie = edge_decoder(obj["movie"])
        # 返回Edge实例(soup暂时传None,后续可以根据name/title重新爬取)
        return Edge(actor, movie)
    # 还原Actor实例
    elif "__type__" in obj and obj["__type__"] == "Actor":
        return Actor(name=obj["name"], soup=None)
    # 还原Movie实例
    elif "__type__" in obj and obj["__type__"] == "Movie":
        return Movie(title=obj["title"], soup=None)
    # 非自定义类的对象直接返回
    return obj

第三步:测试序列化+反序列化流程

现在咱们来验证一下整个流程是否能正常工作:

# 创建测试对象
test_actor = Actor(name="汤姆·汉克斯", soup=None)
test_movie = Movie(title="阿甘正传", soup=None)
test_edge = Edge(test_actor, test_movie)

# 序列化Edge列表到JSON字符串
json_str = json.dumps([test_edge], cls=EdgeEncoder)
print("序列化后的JSON:", json_str)

# 反序列化JSON字符串回Edge列表
restored_edges = json.loads(json_str, object_hook=edge_decoder)
print("\n反序列化后的结果:")
print(f"演员姓名:{restored_edges[0].actor.name}")
print(f"电影名称:{restored_edges[0].movie.title}")

关键注意点

  • 类型标识是核心:一定要在编码器里给每个自定义类加上__type__,否则解码器不知道该还原成哪个类
  • 不可序列化属性的处理:像BeautifulSoup的soup对象无法被JSON序列化,所以编码器里要忽略它,解码器里可以传None,之后如果需要可以根据name/title重新爬取页面生成soup
  • 嵌套处理:因为Edge里包含Actor和Movie,所以解码器要递归处理嵌套的字典,确保所有自定义类都能被正确还原

内容的提问来源于stack exchange,提问作者lmotl3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:24:05