System.Text.Json与Newtonsoft.Json跨库序列化兼容问题咨询
解决System.Text.Json与Newtonsoft.Json在IoT Hub SDK场景下的兼容问题
针对你遇到的双JSON库兼容问题,这里有几个务实的解决思路:
1. 给System.Text.Json加自定义转换器,直接反序列化为CLR基础类型
写一个自定义JsonConverter<object>,让System.Text.Json在反序列化Dictionary<string, object>时,自动把JsonElement转成对应的CLR类型(比如string、int、bool,或者嵌套的字典/列表),这样生成的字典就能直接被Newtonsoft.Json正常序列化。
示例代码:
public class ObjectToJsonElementConverter : JsonConverter<object> { public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.TokenType switch { JsonTokenType.String => reader.GetString(), JsonTokenType.Number when reader.TryGetInt64(out long l) => l, JsonTokenType.Number when reader.TryGetDouble(out double d) => d, JsonTokenType.True => true, JsonTokenType.False => false, JsonTokenType.Null => null, JsonTokenType.StartObject => JsonSerializer.Deserialize<Dictionary<string, object>>(ref reader, options), JsonTokenType.StartArray => JsonSerializer.Deserialize<List<object>>(ref reader, options), _ => JsonDocument.ParseValue(ref reader).RootElement.Clone() }; } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, value.GetType(), options); } }
使用时把转换器加入序列化配置:
var options = new JsonSerializerOptions(); options.Converters.Add(new ObjectToJsonElementConverter()); var dict = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString, options);
这样反序列化后的dict["route1"]会是string类型,dict["route2"]会是对应的CLR对象,Newtonsoft.Json序列化这个字典时就不会报错。
2. 隔离双库的使用范围
既然IoT Hub SDK依赖Newtonsoft.Json,那就把与SDK交互的部分统一用Newtonsoft.Json处理,新开发的模块单独用System.Text.Json。比如:
- 当需要把数据传给IoT Hub SDK时,直接用Newtonsoft.Json反序列化JSON字符串为
Dictionary<string, object> - 新功能的JSON处理完全用System.Text.Json,和SDK交互时再做一次类型转换(比如把System.Text.Json生成的对象转成Newtonsoft.Json的JObject,再转成Dictionary)
3. 手动转换JsonElement为CLR对象
如果不想加转换器,也可以写一个递归转换方法,把System.Text.Json生成的Dictionary<string, JsonElement>(或者Dictionary<string, object>里的JsonElement)转成普通的CLR对象字典:
public static object ConvertJsonElementToObject(JsonElement element) { return element.ValueKind switch { JsonValueKind.String => element.GetString(), JsonValueKind.Number => element.TryGetInt64(out long l) ? l : element.GetDouble(), JsonValueKind.True => true, JsonValueKind.False => false, JsonValueKind.Null => null, JsonValueKind.Object => element.EnumerateObject() .ToDictionary(kv => kv.Name, kv => ConvertJsonElementToObject(kv.Value)), JsonValueKind.Array => element.EnumerateArray() .Select(ConvertJsonElementToObject) .ToList(), _ => element.ToString() }; }
使用时:
var tempDict = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(jsonString); var targetDict = tempDict.ToDictionary(kv => kv.Key, kv => ConvertJsonElementToObject(kv.Value));
内容的提问来源于stack exchange,提问作者adelb
相关产品推荐
相关产品推荐

