我将以下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
的节点。
但是,如果我想从ParentA
节点获取p2
节点。我不得不说
JToken p1 = p2.Parent.Parent.Parent.Parent.Parent;
Console.WriteLine(((JProperty)p1).Name);
上面的代码打印"ProductA"
。但令人困惑的部分是,为什么我必须打电话给父母5次。
当我查看我的文档时,我可以看到"children"
是"ProductC"
的父级,然后"ProductA"
是孩子的父级。因此,对Parent
的2次调用应该让我ParentA
。
为什么我需要5个电话?
答案 0 :(得分:8)
您正在遍历的层次结构是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
没有名称,您将获得JProperty
的名称。
我无法告诉你如何在json字符串中描述它如何访问它,它似乎不是一个选项。但是你当然可以编写一些辅助方法来为你获取它们。
这是获取父对象的一个实现。我不知道我们想要跳过的其他JTokens,但这是一个开始。只需传入您想要获得父级的令牌即可。传入可选的父母编号,以指示您想要的父母。
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();
}