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

如何将Python对象写入JSON文件?嵌套类对象序列化报错求助

解决自定义类对象无法JSON序列化的问题

咱先把报错的根源说清楚:Python自带的json模块天生只认识原生数据类型——比如字典、列表、字符串、数字这些常规玩意儿。你定义的Process、Lanes、Tasks都是自己造的类实例,json模块哪见过这些啊?它完全不知道该怎么把这些对象转成JSON格式的字符串,所以直接给你抛了Object of type 'Process' is not JSON serializable这个错误。

下面给你三种实用的解决办法,从简单到灵活,你按需选:

方法一:用__dict__快速转字典(上手最快)

Python的类实例都自带一个__dict__属性,它会把对象里所有的实例变量打包成一个字典。你只要把自定义对象转成这个字典,json模块就能认了。

比如你原来的代码可能是这样:

import json

# 假设你已经创建了一个Process实例
my_process = Process(...)
with open('process_output.json', 'w') as f:
    json.dump(my_process, f)

改成这样就行:

import json

my_process = Process(...)
# 先把Process对象转成字典
process_dict = my_process.__dict__
# 因为你的结构是嵌套的,Lanes和Tasks也是自定义类,得逐层转
process_dict['lanes'] = [lane.__dict__ for lane in process_dict['lanes']]
# 再把每个Lanes里的Tasks也转成字典列表
for lane_item in process_dict['lanes']:
    lane_item['tasks'] = [task.__dict__ for task in lane_item['tasks']]

# 现在就能正常写入JSON了,加个indent=4让格式更好看
with open('process_output.json', 'w') as f:
    json.dump(process_dict, f, indent=4)

这个方法的优点是零额外代码,上手快;缺点是如果你的类里有私有变量(比如以_开头的),也会被一起序列化进去,要是不想让这些内容出现在JSON里,就得换别的方法。

方法二:自定义JSON编码器(适合嵌套结构)

如果你的嵌套层级比较多,手动转__dict__太麻烦,那可以自己写个编码器,让json模块自动识别你的自定义类。

代码示例:

import json

# 继承JSONEncoder写自己的编码器
class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        # 只要是你的自定义类实例,就返回它的__dict__
        if isinstance(obj, (Process, Lanes, Tasks)):
            return obj.__dict__
        # 其他类型交给父类处理,避免破坏原生类型的序列化
        return super().default(obj)

# 使用的时候指定cls参数就行,不用手动转嵌套对象
my_process = Process(...)
with open('process_output.json', 'w') as f:
    json.dump(my_process, f, cls=CustomJSONEncoder, indent=4)

这种方法一劳永逸,不管嵌套多少层,只要是你指定的自定义类,都会自动被转成字典,非常适合你这种Process包含Lanes数组、Lanes包含Tasks数组的结构。

方法三:给类加__json__方法(最规范可控)

如果想精准控制每个类要序列化哪些字段,甚至对字段做一些转换(比如把日期转成特定格式的字符串),可以给每个自定义类加一个__json__方法,专门返回要序列化的内容。

示例代码:

class Process:
    def __init__(self, lanes, process_name, create_time):
        self.lanes = lanes
        self.process_name = process_name
        self.create_time = create_time  # 假设是datetime对象
        self._private_var = "不想序列化的内容"  # 私有变量
    
    def __json__(self):
        # 只返回你想要的字段,还能做转换,比如把datetime转成字符串
        return {
            'process_name': self.process_name,
            'create_time': self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
            'lanes': [lane.__json__() for lane in self.lanes]
        }

class Lanes:
    def __init__(self, tasks, lane_id):
        self.tasks = tasks
        self.lane_id = lane_id
    
    def __json__(self):
        return {
            'lane_id': self.lane_id,
            'tasks': [task.__json__() for task in self.tasks]
        }

class Tasks:
    def __init__(self, task_name, task_status):
        self.task_name = task_name
        self.task_status = task_status
    
    def __json__(self):
        return {
            'task_name': self.task_name,
            'task_status': self.task_status
        }

然后序列化的时候,调用__json__()拿到字典再写入:

import json

my_process = Process(...)
with open('process_output.json', 'w') as f:
    json.dump(my_process.__json__(), f, indent=4)

这种方式最规范,能完全掌控序列化的内容,后期维护也方便,适合长期迭代的项目。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:24:58