我正在寻找一种方法,使用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
的所有对象,因此只有属性engine
的对象的值为V6
。
tl;问题:
答案 0 :(得分:4)
您可以像这样建模数据:
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);
答案 1 :(得分:4)
当没有预定义架构时,您可以使用LINQ to JSON来解析和过滤JSON对象。
首先,使用JObject
将您的JSON解析为JToken.Parse()
。然后,您可以使用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;
}
}
示例fiddle。
注意 - 您也可以考虑使用支持SelectTokens()
的JSONPath query syntax,例如:
var someProp = "id";
var someValue = "3";
var filterString = string.Format(@"..*[?(@.{0} == '{1}')]", someProp, someValue);
var filteredObjs = root.SelectTokens(filterString).ToArray();
但是,您的JSON包含直接嵌套在其他对象中的对象,而Newtonsoft的JSONPath实现找不到这样的直接嵌套对象,如JSONPath scripts not executing correctly for objects #1256中所述。