MongoDB存储含Player列表的AccountDetails时提示序列化深度超限疑似循环引用
问题根源
- 核心认知偏差:
[JsonIgnore]是JSON序列化框架的专属标记,MongoDB .NET驱动的Bson序列化器完全不识别该特性,所有被你标记[JsonIgnore]的字段,默认都会被驱动纳入序列化流程,这是你排查不到循环引用的核心原因。 - 具体触发循环的高风险字段:
- GameObj类下的
[JsonIgnore] public Instance Instance { get; set; }:游戏场景Instance类几乎必然持有当前场景所有实体(包含当前Player对象)的集合引用,直接形成递归链:AccountDetails→Players列表 →Player→ 继承的Instance→Instance实体列表 → 回指当前Player,无限套娃触发深度上限。 - Player类下的
[JsonIgnore] public List<Node> Path:如果Node类定义包含回指所属玩家、父/根节点的引用,也会形成闭环。 - 未展示定义的
Skill、Attribute、PlayerClass类:任意属性持有当前Player、AccountDetails的强引用,都会触发同类问题。
- GameObj类下的
修复方案
- 第一步:替换MongoDB专属序列化忽略标记
把所有运行时临时、不需要持久化的字段,从[JsonIgnore]改为MongoDB驱动专属的[BsonIgnore],示例:
必须替换的字段清单:// 原标记(MongoDB不认) [JsonIgnore] public Instance Instance { get; set; } // 替换为MongoDB可识别的忽略标记 [BsonIgnore] public Instance Instance { get; set; }- Player类下的
Path、PathCount、HealthTick/AttackTick/AnimTick/MaxAnimTick - GameObj类下的
Instance、playerInteractions、LastProcessedSequence(如果InstanceID不需要持久化也一并标记)
- Player类下的
- 第二步:校验剩余可持久化字段的引用链
对未被标记忽略的属性(Skills、Attributes、Class、TargetEntity等),逐个检查对应类定义,确保不存在指向当前Player、AccountDetails的反向强引用,必要时对不需要持久化的引用也标记[BsonIgnore]。 - 第三步(调试用):临时调高序列化深度阈值
如果需要快速定位具体触发循环的字段,可临时调高MongoDB驱动的最大序列化深度上限,通过输出的完整递归栈锁定具体闭环位置,调试完成后改回默认阈值避免性能损耗。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

