Json.Net - 不返回直接父路径 [英] Json.Net - Immediate parent path not being returned
问题描述
我正在尝试检索通过 SelectToken 找到的 JToken 对象的直接父级的路径.
- 祖父母
- 父母
- 对象
- 父母
在上述结构中,object.Path 的值是grandparent.parent.object",object.Parent.Path 的值也是grandparent.parent".对象".
这是一个错误还是应该以其他方式检索父路径?
下面是一个说明 object.Path 和 object.Parent.Path 相同的示例:
var input = "{'grandparent': {'parent': {'object':'value'}}}";var jsonInput = JObject.Parse(input);var jsonObject = jsonInput.SelectToken("..object");var path = jsonObject.Path;//祖父母.parent.objectvar parentPath = jsonObject.Parent.Path;//grandparent.parent.object(与对象相同)var realParentPath = jsonObject.Parent.Parent.Path;//grandparent.parent(实际父路径)
您偶然发现了 Json.NET 的一个实现细节,它对具有两级容器的 JSON 对象进行建模,即
JObject
对应大括号之间的整个部分,JProperty
对应特定的 string : value
部分.
我认为选择此实现是为了将名称与值分开,以便 JValue
可用于数组和对象原始值,而无需为数组项添加无意义的 Name
属性.但是,从SelectToken
,JProperty
的存在有点尴尬,因为它不对应任何可通过 JSONPath 查询,因为 SelectToken
总是返回实际值而不是容器属性.Newtonsoft 选择使 JProperty.Path
与其值的路径相同;可能他们本可以选择让 JProperty.Path
抛出异常,但他们没有.
为了隐藏这个实现细节,你可以引入一个扩展方法SelectableParent()
:
公共静态部分类JsonExtensions{公共静态 JToken SelectableParent(这个 JToken 令牌){如果(令牌==空)返回空;var parent = token.Parent;如果(父母是 JProperty)父母 = parent.Parent;返回父母;}}
然后按如下方式使用:
var path = jsonObject.Path;//祖父母.parent.objectvar parentPath = jsonObject.SelectableParent().Path;//祖父母.parent
演示小提琴 此处.
相关:与 SelectToken 一起使用时,为什么 AddAfterSelf 返回JProperty 不能有多个值"?em>.
I am attempting to retrieve the path of the immediate parent of a JToken object found via SelectToken.
- grandparent
- parent
- object
- parent
In above structure the value of object.Path is "grandparent.parent.object" and the value of object.Parent.Path is also "grandparent.parent.object".
Is this a bug or should the path of a parent be retrieved in another way?
Below is an example that illustrates object.Path and object.Parent.Path being the same:
var input = "{'grandparent': { 'parent' : {'object' : 'value'}}}";
var jsonInput = JObject.Parse(input);
var jsonObject = jsonInput.SelectToken("..object");
var path = jsonObject.Path; //grandparent.parent.object
var parentPath = jsonObject.Parent.Path; //grandparent.parent.object (same as object)
var realParentPath = jsonObject.Parent.Parent.Path; //grandparent.parent (actual parent path)
You have stumbled on an implementation detail of Json.NET, which is that it models a JSON object with two levels of container, namely the JObject
which contains a collection of JProperty
items, each of which in turn contains the actual property value:
JObject // A JSON object: an unordered set of name/value pairs
-> IEnumerable<JProperty> Properties()
JProperty // A property name/value pair
-> string Name // The property name
-> JToken Value // The property value
I.e., using the diagram for an object from https://json.org/:
The JObject
corresponds to the entire section between braces, and the JProperty
corresponds to a specific string : value
portion.
I reckon this implementation was chosen to separate the name from the value, so that JValue
could be used for both array and object primitive values, without having to add in a meaningless Name
property for array items. However, from the point of view of SelectToken
, the existence of JProperty
is a bit awkward because it doesn't correspond to anything selectable via a JSONPath query since SelectToken
always returns the actual value rather than the container property. Newtonsoft chose to make JProperty.Path
the same as it's value's path; possibly they could have chosen to make JProperty.Path
throw an exception instead, but they did not.
To hide this implementation detail, you could introduce an extension method SelectableParent()
:
public static partial class JsonExtensions
{
public static JToken SelectableParent(this JToken token)
{
if (token == null)
return null;
var parent = token.Parent;
if (parent is JProperty)
parent = parent.Parent;
return parent;
}
}
Then use it as follows:
var path = jsonObject.Path; //grandparent.parent.object
var parentPath = jsonObject.SelectableParent().Path; //grandparent.parent
Demo fiddle here.
Related: Why does AddAfterSelf return 'JProperty cannot have multiple values' when used with SelectToken?.
这篇关于Json.Net - 不返回直接父路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!