如何正确将JSON反序列化为C#值元组List<(string, bool)>?
解决Newtonsoft.Json反序列化JSON到命名值元组的问题
嘿,这个问题我之前折腾过好一会儿!Newtonsoft.Json默认对命名值元组的反序列化支持确实有点坑——因为值元组的命名元素只是编译时的语法糖,到了运行时,元组的实际属性还是Item1、Item2这类默认命名,和你JSON里的foo、bar完全对应不上,所以才会返回默认值列表。
不过不用慌,咱们完全不用额外创建模型类,只需要写一个简单的自定义JSON转换器就能搞定!
步骤1:编写针对目标值元组的自定义转换器
这个转换器会手动把JSON对象里的字段映射到值元组的对应元素:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; public class FooBarTupleConverter : JsonConverter<(string foo, bool bar)> { // 反序列化逻辑:从JSON读取数据并组装成值元组 public override (string foo, bool bar) ReadJson(JsonReader reader, Type objectType, (string foo, bool bar) existingValue, bool hasExistingValue, JsonSerializer serializer) { var jsonObject = JObject.Load(reader); // 读取字段值,可根据需求添加空值处理逻辑 return ( foo: jsonObject["foo"]?.Value<string>() ?? string.Empty, bar: jsonObject["bar"]?.Value<bool>() ?? false ); } // 序列化逻辑(如果需要把元组转回JSON的话) public override void WriteJson(JsonWriter writer, (string foo, bool bar) value, JsonSerializer serializer) { var jsonObject = new JObject(); jsonObject["foo"] = value.foo; jsonObject["bar"] = value.bar; jsonObject.WriteTo(writer); } }
步骤2:使用转换器进行反序列化
在调用JsonConvert.DeserializeObject时,把自定义转换器作为参数传入即可:
string json = @"[{""foo"": ""1"", ""bar"": false}, {""foo"": ""2"", ""bar"": false}]"; var result = JsonConvert.DeserializeObject<List<(string foo, bool bar)>>(json, new FooBarTupleConverter());
为什么默认方式不行?
再啰嗦两句原因:值元组的foo、bar命名只是给编译器看的语法糖,编译后这些名称会被丢弃,CLR只认识Item1(对应foo)、Item2(对应bar)。而Newtonsoft.Json默认只会尝试把JSON字段映射到元组的Item1、Item2属性,你的JSON里根本没有这些字段,所以就只能返回元组的默认值(null, false)了。
如果你的项目里需要处理多种不同的命名值元组,也可以写一个通用的转换器(通过反射获取元组的命名元素信息),不过针对你这个特定场景,上面的专用转换器已经足够简单好用啦!
内容的提问来源于stack exchange,提问作者anatol
相关产品推荐
相关产品推荐

