JSON反序列化后用Linq/Lambda过滤特定值失败,代码返回0条结果
Linq筛选动态对象无结果的问题排查及解决
场景说明
API返回的JSON响应:
"table1": [ { "abc": "test", "def": "test1" }, { "abc": "test2", "def": "User1" } ]
该响应被绑定到C#属性:
public List<object>? table1 { get; set; }
需要筛选出def字段值为User1或User2的项,但执行以下代码后返回0条记录:
var filteredList = table1 .Where(item => item.GetType().GetProperty("def",BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase)?.GetValue(item)?.ToString() is "User1" or "User2") .ToList();
问题原因
- 动态对象类型不匹配:JSON反序列化后,
List<object>中的元素并不是普通的.NET对象,而是JSON库的专用类型(比如Newtonsoft.Json的JObject,或者System.Text.Json的JsonElement)。这些类型没有名为def的公共实例属性,所以GetProperty("def")会返回null,导致后续的取值和判断全部失效。 - 模式匹配的潜在问题:
is "User1" or "User2"是引用相等判断,虽然字符串字面量在编译时会被 intern 化,多数情况下能正常工作,但相比值相等的==不够稳妥,不过这不是本次无结果的主要原因。
解决方法
方法一:针对JSON库的动态访问
根据你使用的JSON序列化库,直接通过键值方式访问字段:
- 使用Newtonsoft.Json(Json.NET):
var filteredList = table1 .OfType<JObject>() // 先转换为JObject类型 .Where(item => item["def"]?.ToString() == "User1" || item["def"]?.ToString() == "User2") .ToList();
- 使用System.Text.Json:
var filteredList = table1 .OfType<JsonElement>() // 先转换为JsonElement类型 .Where(item => item.TryGetProperty("def", out var defValue) && (defValue.GetString() == "User1" || defValue.GetString() == "User2")) .ToList();
方法二:使用强类型(推荐)
创建对应JSON结构的实体类,替换List<object>,这样代码更简洁且类型安全:
// 定义实体类 public class TableItem { public string? abc { get; set; } public string? def { get; set; } } // 修改绑定属性 public List<TableItem>? table1 { get; set; } // 筛选代码 var filteredList = table1 .Where(item => item.def is "User1" or "User2") .ToList();
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

