.NET 8带$id引用的字典构造函数反序列化报错求解
解决方法(无需自定义转换器)
出现这个错误的核心原因是:当启用ReferenceHandler.Preserve时,System.Text.Json在反序列化构造函数参数阶段,还未建立引用跟踪机制,无法处理带有$id元数据的复杂类型参数(比如你的Dictionary<string, int>)。以下是两种无需自定义转换器的可行方案:
方案一:将初始化逻辑移至反序列化后执行
把依赖Dictionary的初始化代码从构造函数移到[OnDeserialized]标记的方法中,同时将构造函数改为无参私有形式:
public Dictionary<string, int> MyDictionary { get; set; } = new(); // 无参私有构造函数,供Json反序列化调用 private MyClass() { } [OnDeserialized] private void OnDeserialized(StreamingContext context) { // 这里执行原来构造函数中的setup逻辑 // ...doing some other setup stuff }
这样System.Text.Json会先完成MyDictionary的反序列化(包括处理$id引用),再调用OnDeserialized方法执行初始化操作,避开了构造函数参数无法处理引用的问题。
方案二:构造函数接收JsonElement并手动反序列化
保留构造函数,但将参数类型改为JsonElement,同时接收JsonSerializerOptions,手动完成Dictionary的反序列化:
public Dictionary<string, int> MyDictionary { get; set; } = new(); [JsonConstructor] private MyClass(JsonElement myDictionaryElement, JsonSerializerOptions options) { // 使用当前反序列化配置(包含ReferenceHandler.Preserve)手动反序列化Dictionary MyDictionary = JsonSerializer.Deserialize<Dictionary<string, int>>(myDictionaryElement, options); // ...doing some other setup stuff }
这种方式让你可以继续保留构造函数的初始化逻辑,同时通过手动反序列化处理引用元数据。
注意事项
- 确保你的
JsonSerializerOptions确实启用了ReferenceHandler = ReferenceHandler.Preserve,否则无法正确处理$id引用。 - 方案一的侵入性更低,更推荐用于大多数场景;方案二更适合必须在构造阶段完成初始化的场景。
内容的提问来源于stack exchange,提问作者AKuhlmann
相关产品推荐
相关产品推荐

