Newtonsoft.Json反序列化带排序逻辑的自定义集合失败问题
问题根因
Newtonsoft.Json 处理可读写的集合类型属性时,默认反序列化流程为:
- 调用属性getter获取现有集合实例
- 将反序列化得到的所有元素逐个Add到该实例中
你修改后的属性getter每次执行都会通过OrderBy(...).ToList()生成一个和后备字段_inventoryItems无关联的全新List实例。反序列化器添加元素的操作全部作用在这个临时生成的List上,操作完成后临时实例被回收,真正的后备字段始终保持初始化的空列表状态,最终读取到的Items自然是空的。
无需自定义转换器的解决方法
方案1(推荐):调整排序逻辑位置,符合反序列化默认逻辑
把排序逻辑从getter移到setter,保证getter直接返回后备字段的真实引用,既兼容默认反序列化行为,还能避免每次访问属性都重复排序、生成新集合的性能损耗:
class Inventory { private List<InventoryItem> _inventoryItems = new(); public List<InventoryItem> Items { get => _inventoryItems; set { _inventoryItems = value == null ? new List<InventoryItem>() : value.OrderBy(t => t.Start).ToList(); } } }
这种实现下,无论是外部赋值还是Json反序列化,存入后备字段的集合永远是按Start字段排好序的,读取时直接返回即可,没有额外开销。
方案2:修改反序列化配置,适配原有属性写法
如果业务场景必须保留getter动态排序返回新集合的逻辑,不需要修改类代码,只要调整反序列化设置,让Json.NET直接生成完整集合后调用setter赋值,跳过逐个Add的流程即可:
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }; var inventory = JsonConvert.DeserializeObject<Inventory>(serialization, deserializeSettings);
如果需要全局生效,直接将该配置赋值给JsonConvert.DefaultSettings即可,所有反序列化操作都会自动应用该规则。
内容的提问来源于stack exchange,提问作者Aaron Haspel
相关产品推荐
相关产品推荐

