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

时间:2019-03-19 15:37:40

标签: path json.net parent jsonpath

我正在尝试检索通过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; //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)

2 个答案:

答案 0 :(得分: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 :(得分: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"
//}
相关问题