我正在寻找一种方法来使用Json.NET选择JObject
中的所有对象
{
"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
的所有对象,因此只有具有属性engine
且值为V6
的对象。
tl;dr问题:
- 如何获得JObject中嵌套的所有对象的列表
- (奖励)只获得具有特定属性的对象
当没有预定义的模式时,可以使用LINQ to JSON来解析和过滤JSON对象。
首先,使用JToken.Parse()
将JSON解析为JObject
。然后,您可以使用JContainer.DescendantsAndSelf()
按文档顺序遍历该根对象及其所有子代标记。(或者,如果您想跳过根对象,请使用JContainer.Descendants()
。)然后,您可以使用.OfType<JObject>()
进行筛选,以返回所有对象,无论是否嵌套:
var root = JObject.Parse(jsonString;
var allObjs = root.DescendantsAndSelf()
.OfType<JObject>()
.ToArray();
要按某个值进行筛选,可以添加一个额外的Where()
子句,如以下扩展方法所示:
public static partial class JTokenExtensions
{
public static JObject [] FilterObjects<T>(this JObject root, string someProp, T someValue)
{
var comparer = new JTokenEqualityComparer();
var someValueToken = JToken.FromObject(someValue);
var objs = root.DescendantsAndSelf()
.OfType<JObject>()
.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<T>(this JObject root, string someProp, T someValue)
{
var comparer = EqualityComparer<T>.Default;
var objs = root.DescendantsAndSelf()
.OfType<JObject>()
.Where(t => { var v = t[someProp]; return v != null && (someValue == null ? v.IsNull() : comparer.Equals(v.ToObject<T>(), 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<Car> 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<Carpark>(myJsonString);
foreach(var car in carpark.Cars.Where(c => c.Engine.ToLower().Contains("v6"))
Console.WriteLine(car.Model);