使用JsonConvert反序列化动态对象及列表时如何省略‘Value’获取属性?
解决Newtonsoft.Json动态反序列化时无需
.Value获取属性的问题 单个动态对象的处理
你遇到的情况是因为Newtonsoft.Json返回的dynamic其实是它自己的JObject/JValue类型,不是原生的CLR动态对象,所以直接访问属性拿到的是JValue实例,必须通过.Value才能取到实际值。要跳过.Value直接获取属性,有两种实用方法:
方法1:反序列化为ExpandoObject(推荐)
ExpandoObject是CLR原生的动态类型,配合ExpandoObjectConverter反序列化后,就能像访问普通类属性一样直接取值:
string entities = "{\"Property\":\"\"}"; var entity = JsonConvert.DeserializeObject<ExpandoObject>(entities, new ExpandoObjectConverter()) as dynamic; var propertyValue = entity.Property; // 直接获取,无需.Value
这样处理后,entity的属性直接对应实际值,完全不需要额外的.Value调用。
方法2:利用隐式类型转换
你已经发现用string接收时直接是字符串,这是因为JValue实现了到基本类型的隐式转换。如果只是针对单个属性,也可以显式转换:
string entities = "{\"Property\":\"test value\"}"; dynamic entity = JsonConvert.DeserializeObject<dynamic>(entities); string propertyValue = entity.Property; // 隐式转换自动取出Value // 或者显式转换:var propertyValue = (string)entity.Property;
不过这种方法只适合明确知道属性类型的场景,通用性不如ExpandoObject。
动态对象列表的处理
要反序列化动态对象列表且无需.Value,同样可以用ExpandoObject的列表,再转成dynamic集合:
string jsonList = "[{\"Property\":\"Value1\"}, {\"Property\":\"Value2\"}]"; // 反序列化为ExpandoObject列表,再转为dynamic集合 var dynamicList = JsonConvert.DeserializeObject<List<ExpandoObject>>(jsonList, new ExpandoObjectConverter()) .Cast<dynamic>() .ToList(); // 直接遍历访问属性 foreach (var item in dynamicList) { string value = item.Property; Console.WriteLine(value); }
这样每个列表项都是ExpandoObject转成的dynamic,可以直接访问属性,不用再处理.Value。
补充:为什么var和string接收结果不同?
当你用var接收entity.Property时,变量类型会保留JValue(因为dynamic返回的是Json.NET的类型),所以必须手动取.Value;而当你用string接收时,JValue的隐式转换运算符会自动把内部的实际值提取出来赋值给字符串变量,所以不需要额外操作。
内容的提问来源于stack exchange,提问作者Dilshod K
相关产品推荐
相关产品推荐

