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

如何在JSON序列化/反序列化后保留Python对象的引用链接

如何让JSON序列化保留Python对象的引用关联?

JSON本身不支持对象引用的原生表达,默认序列化会将每个对象引用转化为独立的JSON结构,导致反序列化后原有的引用关联丢失。要解决这个问题,有两种常用实现思路:

方法一:使用支持引用保留的序列化库(如jsonpickle)

jsonpickle是专为Python设计的序列化库,能自动处理对象引用——序列化时为每个唯一对象生成标识符,反序列化时自动重建引用关联。

修改后的测试代码

import jsonpickle
import CompositeStandard as cs

# 测试逻辑
obj = cs.CompositeDB()
obj.allComposite = [cs.Ply(defects=[cs.Wrinkle()])]
obj.allDefects = [obj.allComposite[0].defects[0]]  # 引用同一个对象

obj.allDefects[0].area = 678  # 修改同步到两个引用
print(obj)
print("\n\n")

# 序列化,开启引用支持
json_str = jsonpickle.encode(obj, unpicklable=True)

# 保存到文件
with open('D:\\CAD_library_sampling\\CompoST_examples\\test_sd.json', 'w') as out_file:
    out_file.write(json_str)

# 读取并反序列化
with open('D:\\CAD_library_sampling\\CompoST_examples\\test_sd.json', "r") as in_file:
    json_str = in_file.read()

D = jsonpickle.decode(json_str)

D.allDefects[0].area = 99999  # 修改同步到两个引用
print("\n\n\n")
print(D.allDefects[0]) 
print("\n\n\n")
print(D.allComposite[0].defects[0])  # 现在会打印"area=99999"

方法二:自定义序列化逻辑,手动管理对象引用

如果需要完全控制JSON格式,可以给需要被引用的对象添加唯一标识符,序列化时记录对象ID,反序列化时先创建所有对象,再根据ID重建引用关系。

步骤1:给需要引用的类添加唯一ID属性

修改CompositeStandard中的类示例:

import uuid

class Wrinkle:
    def __init__(self):
        self._id = str(uuid.uuid4())
        self.area = 0

# 同理给Ply、CompositeDB等类按需添加_id属性

步骤2:自定义序列化与反序列化函数

import json

def serialize_with_ref(obj):
    # 用字典记录所有对象的ID和数据
    obj_map = {}
    # 递归遍历对象,收集所有带_id的对象
    def traverse(item):
        if hasattr(item, "_id") and item._id not in obj_map:
            obj_dict = item.__dict__.copy()
            obj_map[item._id] = obj_dict
            # 遍历属性,将嵌套对象替换为引用标记
            for key, value in obj_dict.items():
                if isinstance(value, list):
                    for idx, elem in enumerate(value):
                        if hasattr(elem, "_id"):
                            value[idx] = {"$ref": elem._id}
                        else:
                            traverse(elem)
                elif hasattr(value, "_id"):
                    obj_dict[key] = {"$ref": value._id}
                else:
                    traverse(value)
        elif isinstance(item, list):
            for elem in item:
                traverse(elem)
        elif isinstance(item, dict):
            for value in item.values():
                traverse(value)
    traverse(obj)
    # 保存根对象ID和所有对象映射
    return json.dumps({
        "root_id": obj._id,
        "objects": obj_map
    })

def deserialize_with_ref(json_str):
    data = json.loads(json_str)
    obj_map = {}
    # 先创建所有对象实例
    for obj_id, obj_dict in data["objects"].items():
        # 根据类特征创建实例,需根据你的实际类结构调整
        if "defects" in obj_dict:
            obj = cs.Ply()
        elif "area" in obj_dict:
            obj = cs.Wrinkle()
        else:
            obj = cs.CompositeDB()
        obj.__dict__.update(obj_dict)
        obj_map[obj_id] = obj
    # 重建引用关系
    def resolve_refs(item):
        if isinstance(item, list):
            for idx, elem in enumerate(item):
                if isinstance(elem, dict) and "$ref" in elem:
                    item[idx] = obj_map[elem["$ref"]]
                else:
                    resolve_refs(elem)
        elif isinstance(item, dict):
            for key, value in item.items():
                if isinstance(value, dict) and "$ref" in value:
                    item[key] = obj_map[value["$ref"]]
                else:
                    resolve_refs(value)
        elif hasattr(item, "__dict__"):
            for key, value in item.__dict__.items():
                if isinstance(value, dict) and "$ref" in value:
                    setattr(item, key, obj_map[value["$ref"]])
                else:
                    resolve_refs(value)
    root_obj = obj_map[data["root_id"]]
    resolve_refs(root_obj)
    return root_obj

使用自定义函数的测试代码

import CompositeStandard as cs
import uuid

# 测试逻辑
obj = cs.CompositeDB()
obj._id = str(uuid.uuid4())
obj.allComposite = [cs.Ply(defects=[cs.Wrinkle()])]
obj.allDefects = [obj.allComposite[0].defects[0]]

obj.allDefects[0].area = 678
print(obj)
print("\n\n")

# 序列化
json_str = serialize_with_ref(obj)

# 保存到文件
with open('D:\\CAD_library_sampling\\CompoST_examples\\test_sd.json', 'w') as out_file:
    out_file.write(json_str)

# 读取并反序列化
with open('D:\\CAD_library_sampling\\CompoST_examples\\test_sd.json', "r") as in_file:
    json_str = in_file.read()

D = deserialize_with_ref(json_str)

D.allDefects[0].area = 99999
print("\n\n\n")
print(D.allDefects[0]) 
print("\n\n\n")
print(D.allComposite[0].defects[0])  # 会打印"area=99999"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 23:10:10