JSON.NET - Confusion about getting a parent from a JToken

I have the following JSON document stored in a text file

{ "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" : {} } 

I wrote this code in C # using the NewtonSoft JSon.NET Library

 string content = File.ReadAllText(@"c:\temp\foo.txt"); JToken token = JToken.Parse(content); JToken p2 = token["children"]["ProductA"]["children"]["ProductC"]; 

This works, and I get node for p2.

However ... if I want node for ParentA from p2 node. I have to say

 JToken p1 = p2.Parent.Parent.Parent.Parent.Parent; Console.WriteLine(((JProperty)p1).Name); 

The above code displays “ProductA” ... But the confusing part is why I have to call the parent “5” times.

When I look at my document, I see that “children” are the parent of “ProductC” and then “ProductA” is the parent for the children. Therefore, 2 parent calls should have received ParentA.

Why do I need 5 calls?

+6
source share
1 answer

The hierarchy you are looking at is how Json.net structures objects, it is not representative of the json string itself.

Regarding the ProductA object (well, one up), here's how you go to ProductC :

 JProperty: "ProductA" -> JObject (ProductA object) -> JProperty: "children" -> JObject (children object) -> JProperty: "ProductC" -> JObject (ProductC object) *you are here 

So, if you look at it this way, you will see that you are actually accessing JProperty "ProductA" (5 parents), and not the object itself. As you may have noticed, JObject has no name, you get the name JProperty .

I can’t tell you exactly how you can access it, as described in the json line, this is not like an option. But you could, of course, write some helper methods to get them for you.

Here is one implementation for getting the parent object. I do not know what other JTokens we will meet that we want to miss, but this is the beginning. Just go to the token you want to receive from the parent. Go to the optional parent number to indicate which parent you want.

 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(); } 
+6
source

All Articles