Json.Net - 未返回直接 parent 路径
Json.Net - Immediate parent path not being returned
我正在尝试检索通过 SelectToken 找到的 JToken object 的直接路径 parent。
- 盛大parent
- parent
- object
在上面的结构中,object.Path的值为"grandparent.parent.object",object.Parent.Path[=35=的值为] 也是 "grandparent.parent.object".
这是一个错误还是应该以其他方式检索 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; //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)
您无意中发现了 Json.NET 的一个实现细节,即它使用两层容器对 JSON 对象建模,即 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
即,使用来自 https://json.org/ 的 object 的图表:
JObject
对应大括号之间的整个部分,JProperty
对应特定的string : value
部分。
我认为选择此实现是为了将名称与值分开,因此 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 查询因为 SelectToken
总是 returns 实际值而不是容器 属性. Newtonsoft 选择使 JProperty.Path
与其值的路径相同;也许他们本可以选择让 JProperty.Path
抛出异常,但他们没有。
要隐藏此实现细节,您可以引入扩展方法 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;
}
}
然后使用如下:
var path = jsonObject.Path; //grandparent.parent.object
var parentPath = jsonObject.SelectableParent().Path; //grandparent.parent
演示 fiddle here.
相关: .
下面的实际例子帮助我理解了 JValue 和它的父级 JProperty 之间的区别。
var input = "{'grandparent': { 'parent' : {'object' : 'value', 'object2': 'value2'}}}";
var jsonInput = JObject.Parse(input);
var jsonObject = jsonInput.SelectToken("..object");
//value
var jsonParentObject = jsonObject.Parent;
//"object": "value"
var jsonParentParentObject = jsonObject.Parent.Parent;
//{
//"object": "value",
//"object2": "value2"
//}
var jsonParentParentParentObject = jsonObject.Parent.Parent.Parent;
//"parent": {
// "object": "value",
// "object2": "value2"
//}
我正在尝试检索通过 SelectToken 找到的 JToken object 的直接路径 parent。
- 盛大parent
- parent
- object
- parent
在上面的结构中,object.Path的值为"grandparent.parent.object",object.Parent.Path[=35=的值为] 也是 "grandparent.parent.object".
这是一个错误还是应该以其他方式检索 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; //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)
您无意中发现了 Json.NET 的一个实现细节,即它使用两层容器对 JSON 对象建模,即 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
即,使用来自 https://json.org/ 的 object 的图表:
JObject
对应大括号之间的整个部分,JProperty
对应特定的string : value
部分。
我认为选择此实现是为了将名称与值分开,因此 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 查询因为 SelectToken
总是 returns 实际值而不是容器 属性. Newtonsoft 选择使 JProperty.Path
与其值的路径相同;也许他们本可以选择让 JProperty.Path
抛出异常,但他们没有。
要隐藏此实现细节,您可以引入扩展方法 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;
}
}
然后使用如下:
var path = jsonObject.Path; //grandparent.parent.object
var parentPath = jsonObject.SelectableParent().Path; //grandparent.parent
演示 fiddle here.
相关:
下面的实际例子帮助我理解了 JValue 和它的父级 JProperty 之间的区别。
var input = "{'grandparent': { 'parent' : {'object' : 'value', 'object2': 'value2'}}}";
var jsonInput = JObject.Parse(input);
var jsonObject = jsonInput.SelectToken("..object");
//value
var jsonParentObject = jsonObject.Parent;
//"object": "value"
var jsonParentParentObject = jsonObject.Parent.Parent;
//{
//"object": "value",
//"object2": "value2"
//}
var jsonParentParentParentObject = jsonObject.Parent.Parent.Parent;
//"parent": {
// "object": "value",
// "object2": "value2"
//}