Replit DB存储Humanoid对象报Circular reference detected错误求助
循环引用报错根因
Replit数据库底层依赖JSON序列化实现数据持久化,你直接将Humanoid自定义类实例写入数据库时,序列化逻辑会遍历实例所有属性:如果你的Humanoid类存在互相引用的属性(比如A单位的目标字段指向B单位,B单位的附近单位列表包含A,或实例持有所属区域/世界对象的引用),就会触发JSON序列化的循环引用检测,抛出对应错误。
解决方案
- 第一步:实现
Humanoid实例的序列化逻辑,仅提取需要跨客户端同步的基础字段,构造纯可JSON序列化的字典结构,不要保留任何引用类型属性
def serialize_humanoid(humanoid): return { "unit_id": humanoid.unit_id, "position": humanoid.position, "hp": humanoid.hp, "nickname": humanoid.nickname, "model_id": humanoid.model_id # 仅添加需要同步的基础属性,不要加入target、所属区域对象等引用类字段 }
- 第二步:按区域维度存储序列化后的单位数据列表,不要直接写入自定义类实例集合
# 示例:写入id为1001的区域内所有人形单位数据 zone_id = 1001 serialized_units = [serialize_humanoid(unit) for unit in zone_1001.all_humanoids] db[f"zone_units_{zone_id}"] = serialized_units
- 第三步:读取数据时反序列化为
Humanoid实例,如有引用关联需求,用唯一id做关联替代直接引用
def deserialize_humanoid(unit_data): humanoid = Humanoid() humanoid.unit_id = unit_data["unit_id"] humanoid.position = unit_data["position"] humanoid.hp = unit_data["hp"] humanoid.nickname = unit_data["nickname"] humanoid.model_id = unit_data["model_id"] return humanoid # 读取区域单位数据示例 zone_unit_data = db.get(f"zone_units_{zone_id}", []) zone_1001.all_humanoids = [deserialize_humanoid(data) for data in zone_unit_data]
- 如果业务需要保留单位间的引用关系,存储时只存对应目标的
unit_id(比如target_id字段),业务逻辑运行时再根据id查询对应实例即可,不要直接存储对象引用。
注意事项
所有写入Replit数据库的值必须是JSON原生支持的类型:字符串、数字、布尔值、列表、字典,禁止直接写入自定义类实例、函数、带循环引用的复合结构。
内容的提问来源于stack exchange,提问作者Akrix
相关产品推荐
相关产品推荐

