JSON.NET – 选择所有对象

我正在寻找一种方法来使用Json.NET选择JObject中的所有对象。 简而言之,如果我有以下JSON:

 { "someCar" : { "id" : "3", "model" : "M7", "engine" : "FI V8", }, "name" : "carparkone", "id" : "1", "cars" : [ { "id" : "1", "model" : "s60", "engine" : "i5", }, { "id" : "2", "model" : "m3", "engine" : "FI V6", }, { "id" : "3", "model" : "M7", "engine" : "FI V8", } ] } 

我会运行一些命令来获取其中所有对象的数组,即{}块中的任何对象。

理想情况下,我会找到someProp具有some value所有对象,因此只有具有值为V6的属性engine对象。

tl;博士问题:

  1. 如何获取嵌套在JObject中的所有对象的列表?
  2. (Bonus)仅获取具有特定属性的对象。

当没有预定义模式时,您可以使用LINQ to JSON来解析和过滤JSON对象。

首先,使用JToken.Parse()将JSON解析为JObject 。 然后,您可以使用JContainer.DescendantsAndSelf()按文档顺序遍历该根对象及其所有后代标记。 (或者如果要跳过根对象,请使用JContainer.Descendants() 。)然后,您可以使用.OfType()过滤所有对象,无论是否嵌套:

 var root = JObject.Parse(jsonString; var allObjs = root.DescendantsAndSelf() .OfType() .ToArray(); 

要按某个值过滤,可以添加一个额外的Where()子句,如以下扩展方法所示:

 public static partial class JTokenExtensions { public static JObject [] FilterObjects(this JObject root, string someProp, T someValue) { var comparer = new JTokenEqualityComparer(); var someValueToken = JToken.FromObject(someValue); var objs = root.DescendantsAndSelf() .OfType() .Where(t => comparer.Equals(t[someProp], someValueToken)) .ToArray(); return objs; } } 

然后做:

 var filteredObjs = root.FilterObjects(someProp, someValue); 

为了使FilterObjects()完全通用,我将所需的值序列化为JToken然后使用JTokenEqualityComparer将实际值与所需的值进行比较。 如果您知道所需的值是基本类型,则可以执行以下操作:

 public static partial class JTokenExtensions { public static bool IsNull(this JToken token) { return token == null || token.Type == JTokenType.Null; } public static JObject[] FilterObjectsSimple(this JObject root, string someProp, T someValue) { var comparer = EqualityComparer.Default; var objs = root.DescendantsAndSelf() .OfType() .Where(t => { var v = t[someProp]; return v != null && (someValue == null ? v.IsNull() : comparer.Equals(v.ToObject(), someValue)); }) .ToArray(); return objs; } } 

样品小提琴 。

注意 – 您可能还考虑使用SelectTokens() ,它支持JSONPath查询语法 ,例如:

 var someProp = "id"; var someValue = "3"; var filterString = string.Format(@"..*[?(@.{0} == '{1}')]", someProp, someValue); var filteredObjs = root.SelectTokens(filterString).ToArray(); 

但是,您的JSON包含直接嵌套在其他对象中的对象,而Newtonsoft的JSONPath实现找不到这样的直接嵌套对象,如JSONPath脚本中没有正确执行对象#1256所述 。

您可以像这样建模数据:

 public class Carpark { [JsonProperty(PropertyName = "name")] public string Name{ get; set; } [JsonProperty(PropertyName = "id")] public int Id {get; set;} [JsonProperty(PropertyName = "cars")] public IEnumerable Cars { get; set; } } public class Car { [JsonProperty(PropertyName = "id")] public int Id { get; set; } [JsonProperty(PropertyName = "model")] public string Model { get; set; } [JsonProperty(PropertyName = "engine")] public string Engine { get; set; } } 

然后使用该模型使用Json.Net反序列化您的字符串。

 var carpark = JsonConvert.DeserializeObject(myJsonString); foreach(var car in carpark.Cars.Where(c => c.Engine.ToLower().Contains("v6")) Console.WriteLine(car.Model);