C#使用LINQ按属性是否存在过滤JToken的问题与实现
原有代码问题
你的代码有3个核心问题,导致运行报错或结果不符合预期:
- 语法错误:
Where方法的lambda表达式闭合符号写错,x => x["id"] == null末尾误用了],应该用)闭合,这个问题会直接导致编译不通过。 - 属性判断逻辑错误:直接用
x["id"] == null无法区分「id属性不存在」和「id属性存在但值为null」两种场景,会把id值显式写为null的条目也错误归到无id列表里。 - 容器使用错误:筛选出来的是多个JObject对象组成的列表,直接传入
JObject构造函数会抛出参数异常——JObject只接收键值对形式的JProperty参数,存储对象列表应该用JArray作为容器。
另外你给出的示例数据本身也有C#语法笔误:id=2的条目后缺少逗号、数组末尾多了冗余逗号,直接运行也会报错。
正确实现代码
使用JObject.ContainsKey()方法判断id属性是否存在是最准确的,不会受id实际值的影响,同时用JArray承载列表结构即可:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Linq; // 初始化测试数据(已修正原示例的语法笔误) var inventory = JArray.Parse(@"[ {""id"": 1, ""name"": ""Apple"", ""type"": ""fruit""}, {""id"": 2, ""name"": ""Orange"", ""type"": ""fruit""}, {""name"": ""Squash"", ""type"": ""Vegetable""} ]"); // 筛选包含id属性的令牌 List<JToken> hasIdTokens = inventory .Where(token => token is JObject obj && obj.ContainsKey("id")) .ToList(); // 筛选不包含id属性的令牌 List<JToken> noIdTokens = inventory .Where(token => token is JObject obj && !obj.ContainsKey("id")) .ToList(); // 分别序列化为JSON字符串 string hasIdJson = JsonConvert.SerializeObject(new JArray(hasIdTokens), Formatting.Indented); string noIdJson = JsonConvert.SerializeObject(new JArray(noIdTokens), Formatting.Indented); // 如果需要把两个列表合并为一个JSON存储,可以按如下方式组装 var saveData = new JObject { ["tokensWithId"] = new JArray(hasIdTokens), ["tokensWithoutId"] = new JArray(noIdTokens) }; string finalSaveJson = JsonConvert.SerializeObject(saveData, Formatting.Indented);
补充说明:代码里加了token is JObject obj的类型判断,是为了避免JToken集合中混入非对象类型的令牌(比如字符串值、数组值)时触发类型转换异常,兼容性更好。
内容的提问来源于stack exchange,提问作者newuser
相关产品推荐
相关产品推荐

