首页
/ Newtonsoft.Json 反序列化时意外追加数据的解决方案

Newtonsoft.Json 反序列化时意外追加数据的解决方案

2025-05-21 12:38:44作者:羿妍玫Ivan

问题现象

在使用 Newtonsoft.Json 进行游戏存档数据反序列化时,开发者遇到了一个奇怪的现象:当反序列化包含嵌套字典结构的 JSON 数据时,某些列表中的元素会被意外地追加,而不是简单地覆盖原有数据。

具体表现为:在反序列化后,missions 列表中出现了额外的元素,数量恰好等于 ActionStageSaveData 类中初始化 missions 列表时指定的元素数量。例如,如果初始化代码为 new() { new(), new(), new() },则反序列化后会额外添加 3 个元素。

问题根源

这个问题的根本原因在于 Newtonsoft.Json 的默认反序列化行为。Newtonsoft.Json 默认使用 ObjectCreationHandling.Auto 设置,这意味着:

  1. 对于已存在的集合和对象,Json.NET 会尝试重用它们
  2. 反序列化过程会将 JSON 中的数据添加到现有集合中,而不是替换整个集合
  3. 这种行为对于某些场景可能有用,但在大多数情况下会导致意外的数据追加

解决方案

要解决这个问题,我们需要修改 Newtonsoft.Json 的反序列化设置,明确指定对象创建处理方式:

var settings = new JsonSerializerSettings
{
    ObjectCreationHandling = ObjectCreationHandling.Replace
};
loadedData = JsonConvert.DeserializeObject<GameData>(dataToLoad, settings);

使用 ObjectCreationHandling.Replace 设置后,Json.NET 将:

  1. 在反序列化时创建新对象,而不是重用现有对象
  2. 完全替换目标集合,而不是向其中添加元素
  3. 确保反序列化结果与原始 JSON 数据完全一致

深入理解 ObjectCreationHandling

Newtonsoft.Json 提供了三种对象创建处理方式:

  1. Auto(默认):根据情况自动决定是重用还是替换对象
  2. Reuse:尽可能重用现有对象和集合
  3. Replace:总是创建新对象并替换现有集合

在大多数业务场景中,特别是涉及数据持久化和恢复的场景,Replace 是最安全的选择,因为它能确保反序列化结果与序列化前的数据完全一致。

最佳实践建议

  1. 明确指定序列化设置:不要依赖默认设置,特别是对于重要数据的序列化/反序列化
  2. 考虑使用 DTO 模式:为序列化设计专用的数据传输对象,避免业务逻辑与序列化逻辑耦合
  3. 单元测试验证:编写单元测试验证序列化/反序列化的正确性
  4. 文档记录设置:在项目文档中记录使用的 JSON 序列化设置,方便团队协作

总结

Newtonsoft.Json 的默认反序列化行为可能会导致数据意外追加的问题,特别是在处理嵌套集合时。通过明确设置 ObjectCreationHandling.Replace,开发者可以确保反序列化过程按预期工作,避免数据不一致的问题。理解并正确配置序列化设置是使用任何 JSON 库的重要基础。

登录后查看全文
热门项目推荐
相关项目推荐