Json.Net - 未返回直接父路径

问题描述 投票:1回答:2

我试图检索通过SelectToken找到的JToken对象的直接父对象的路径。

  • 祖父母 亲 宾语

在上面的结构中,object.Path的值是“grandparent.parent.object”,object.Parent.Path的值也是“grandparent.parent.object”。

这是一个错误还是应该以另一种方式检索父路径?

下面是一个示例,说明了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)
path json.net parent jsonpath
2个回答
1
投票

您偶然发现了Json.NET的实现细节,即它使用两级容器建模JSON对象,即JObject,其中包含collectionJProperty项目,每个项目又包含实际属性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/的对象的图表:

JSON object

JObject对应于大括号之间的整个部分,而JProperty对应于特定的string : value部分。

我认为选择此实现是为了将名称与值分开,因此JValue可以用于数组和对象原始值,而不必为数组项添加无意义的Name属性。然而,从SelectToken的观点来看,JProperty的存在有点尴尬,因为它不对应于通过JSONPath查询可选择的任何东西,因为SelectToken总是返回实际值而不是容器属性。 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

演示小提琴here

相关:Why does AddAfterSelf return 'JProperty cannot have multiple values' when used with SelectToken?


1
投票

以下实际示例帮助我理解了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"
//}
© www.soinside.com 2019 - 2024. All rights reserved.