Json.Net - 不返回直接父路径 [英] Json.Net - Immediate parent path not being returned

查看:66
本文介绍了Json.Net - 不返回直接父路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检索通过 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 属性.但是,从SelectTokenJProperty 的存在有点尴尬,因为它不对应任何可通过 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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆