C# 从JToken获得家长的困惑

C# 从JToken获得家长的困惑,c#,json,json.net,C#,Json,Json.net,我将以下JSON文档存储在一个文本文件中 { "attributes": {"attr0":"value0"}, "children" : { "ProductA" : { "attributes": {"attr1":"value1", "attr2":"value2"}, "children" : { "ProductC":{ "attri

我将以下JSON文档存储在一个文本文件中

{
    "attributes": {"attr0":"value0"},
    "children" : {
        "ProductA" : {
            "attributes": {"attr1":"value1", "attr2":"value2"}, 
            "children" : {
                "ProductC":{
                    "attributes": {"attr3":"value3", "attr4":"value4"}, 
                    "children" : {}, 
                    "referencedChildren" : {}
                }
            }, 
            "referencedChildren" : {}
        }, 
        "ProductB" : {
            "attributes": {"attr5":"value5", "attr6":"value6"}, 
            "children" : {}, 
            "referencedChildren" : {}
        }
    },
    "referencedChildren" : {}
}
我使用NewtonSoft JSon.NET库在C#中编写了这段代码

string content = File.ReadAllText(@"c:\temp\foo.txt");
JToken token = JToken.Parse(content);
JToken p2 = token["children"]["ProductA"]["children"]["ProductC"];
这是可行的,我得到了
p2
的节点

但是,如果我想从
p2
节点获取
ParentA
的节点。我不得不说

JToken p1 = p2.Parent.Parent.Parent.Parent.Parent;
Console.WriteLine(((JProperty)p1).Name);
上面的代码打印出
“ProductA”
。但令人困惑的是,为什么我要给父母打5次电话

当我查看文档时,我可以看到
“children”
“ProductC”
的父级,然后
“ProductA”
是子级的父级。因此,对
Parent
的两次调用应该会让我
ParentA


为什么我需要5个调用?

您正在遍历的层次结构是Json.net如何构造对象,它并不代表Json字符串本身

相对于
ProductA
对象(好吧,向上一个),下面是如何进入
ProductC

JProperty: "ProductA"
 -> JObject (ProductA object)
     -> JProperty: "children"
         -> JObject (children object)
             -> JProperty: "ProductC"
                 -> JObject (ProductC object)  *you are here
因此,如果您这样看,您应该看到您实际上是在访问
JProperty
“ProductA”(5个父对象),而不是对象本身。您可能已经注意到,
JObject
s没有名称,您得到的是
JProperty
的名称

我无法告诉您如何访问它,因为json字符串中描述了它,它似乎不是一个选项。但是您当然可以编写一些助手方法来为您获取它们

下面是一个获取父对象的实现。我不知道我们还会遇到哪些我们想跳过的JToken,但这是一个开始。只需传入您要获取其父项的令牌。传入一个可选的父编号,以指示所需的父编号

JToken GetParent(JToken token, int parent = 0)
{
    if (token == null)
        return null;
    if (parent < 0)
        throw new ArgumentOutOfRangeException("Must be positive");

    var skipTokens = new[]
    {
        typeof(JProperty),
    };
    return token.Ancestors()
        .Where(a => skipTokens.All(t => !t.IsInstanceOfType(a)))
        .Skip(parent)
        .FirstOrDefault();
}
JToken GetParent(JToken令牌,int parent=0)
{
if(标记==null)
返回null;
如果(父级<0)
抛出新ArgumentOutOfRangeException(“必须为正”);
var skipTokens=new[]
{
类型(JProperty),
};
返回标记。祖先()
.Where(a=>skipTokens.All(t=>!t.IsInstanceOfType(a)))
.Skip(父级)
.FirstOrDefault();
}

。我一时不知道答案,但那将是我下一步的诊断步骤。