JSON.NET-选择所有对象 [英] JSON.NET - Select All Objects
问题描述
我正在寻找一种使用Json.NET在JObject
中选择所有对象的方法.简而言之,如果我有以下JSON:
I am looking for a method to select ALL the objects in the JObject
using Json.NET. So in short, if I had the following 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",
}
]
}
我将运行一些命令以获取其中所有对象的数组,即{}
块中的所有对象.
I would run some command to get an array of all the objects in it, i.e. anything in {}
blocks.
理想情况下,我会找到someProp
具有some value
的所有对象,因此只有具有engine
属性且值为V6
的对象.
Ideally, I would find all the objects where someProp
has some value
, so only objects that have a property engine
with a value of V6
.
tl; dr问题:
- 如何获取嵌套在JObject中的所有对象的列表?
- (奖励)仅获得具有特定属性的对象.
推荐答案
You can use LINQ to JSON to parse and filter JSON objects when there is no predefined schema.
首先,使用以下命令将JSON解析为 JObject
JToken.Parse()
.然后,您可以使用 JContainer.DescendantsAndSelf()
遍历该根对象,及其所有后代标记(按文档顺序). (或者,如果要跳过根对象,请使用 JContainer.Descendants()
.)然后可以使用
First, parse your JSON to a JObject
using JToken.Parse()
. Then you can use JContainer.DescendantsAndSelf()
to iterate through that root object, and all descendant tokens of it, in document order. (Or use JContainer.Descendants()
if you want to skip the root object.) Then you can filter then using using .OfType<JObject>()
to return all objects whether nested or not:
var root = JObject.Parse(jsonString;
var allObjs = root.DescendantsAndSelf()
.OfType<JObject>()
.ToArray();
To filter by some value, you can add an additional Where()
clause as shown in the following extension method:
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
将实际值与所需值进行比较.如果您知道所需的值是原始类型,则可以执行以下操作:
To make FilterObjects()
be completely generic, I serialize the desired value to a JToken
then use JTokenEqualityComparer
to compare the actual value with the desired value. If you know that the desired value is a primitive type, instead you can do:
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查询语法,例如:
Note - you might also consider using SelectTokens()
, which supports the JSONPath query syntax, e.g.:
var someProp = "id";
var someValue = "3";
var filterString = string.Format(@"..*[?(@.{0} == '{1}')]", someProp, someValue);
var filteredObjs = root.SelectTokens(filterString).ToArray();
但是,您的JSON包含直接嵌套在其他对象内部的对象,并且Newtonsoft的JSONPath实现没有找到这样的直接嵌套的对象,如
However, your JSON includes objects nested directly inside other objects, and Newtonsoft's implementation of JSONPath does not find such directly nested objects, as explained in JSONPath scripts not executing correctly for objects #1256.
这篇关于JSON.NET-选择所有对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!