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;博士问题:
- 如何获取嵌套在JObject中的所有对象的列表?
- (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);