JContainer, JObject, JToken and Linq confusion

* When writing / editing this question, I began to answer my question. Read for more details, but my actual question is at the very end, in bold. Thank you *

I find it difficult to understand when to use JContainer, JObject and JToken. I understand from "standards" that a JObject consists of JProperties and that a JToken is the base abstract class for all JToken types, but I don't understand JContainer.

I am using C # and I just bought LinqPad Pro 5.

I have a JSON data source in a file, so I am deserializing this file content with this statement:

string json; using (StreamReader reader = new StreamReader(@"myjsonfile.json")) { json = reader.ReadToEnd(); } 

At this point, I take the json string object and deserialize it into a JObject (and this may be my mistake - maybe I need to make jsonWork JToken or JContainer?):

 JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json); 

In my JSON data (the string represented by json) I have three objects: the top-level object looks something like this:

 { "Object1" : { ... }, "Object2" : { ... }, "Object3" : { ... } } 

Each object consists of all kinds of tokens (arrays, strings, other objects, etc.), therefore it is dynamic JSON. (I used ellipses as placeholders instead of mutating this question with lots of JSON data.)

I want to handle "Object1", "Object2" and "Object3" separately using Linq. Therefore, ideally, I would like something like this:

 // these lines DO NOT work var jsonObject1 = jsonWork.Children()["Object1"] var jsonObject2 = jsonWork.Children()["Object2"] var jsonObject3 = jsonWork.Children()["Object3"] 

But the above lines do not work.

I used "var" above because I have no idea what type of object I should use: JContainer, JObject, or JToken! Just so you know what I want to do, once the above jsonObject # variable is correctly assigned, I would like to use Linq to query the JSON that they contain. Here is a very simple example:

 var query = from p in jsonObject1 where p.Name == "Name1" select p 

Of course, my Linq will eventually filter for JSON arrays, objects, strings, etc. in the jsonObject variable ... I think that as soon as I go, I can use LinqPad to help me filter JSON with Linq (I may have more questions about the next steps and I will post them on this site). ..

Any ideas?

****** Detail added: Ok, I found that if I use:

 // this line WORKS var jsonObject1 = ((JObject)jsonWork).["Object1"]; 

Then I get the JObject type in jsonObject1. Is this the right approach?

QUESTION: It is not clear to me when / why to use JContainer, when it seems that JToken and JObject objects work with Linq pretty well ... What is the purpose of JContainer ???

+6
source share
2 answers

JContainer is the base class for JSON elements that have children. JObject , JArray , JProperty and JConstructor all inherit from it.

For example, the following code:

 (JObject)JsonConvert.DeserializeObject("[1, 2, 3]") 

InvalidCastException , but if you drop it before JContainer , everything will be fine.

As for your initial question, if you know that you have a JSON object at the top level, you can simply use:

 var jsonWork = JObject.Parse(json); var jsonObject1 = o["Object1"]; 
+8
source

In most cases, you do not need to worry about JContainer . This will help organize and structure LINQ-to-JSON into well-designed code.

JToken hierarchy is as follows:

 JToken - abstract base class JContainer - abstract base class of JTokens that can contain other JTokens JArray - represents a JSON array (contains an ordered list of JTokens) JObject - represents a JSON object (contains a collection of JProperties) JProperty - represents a JSON property (a name/JToken pair inside a JObject) JValue - represents a primitive JSON value (string, number, boolean, null) 

So you see the JObject JContainer , which is a JToken .

Here's the basic rule:

  • If you know that you have an object (indicated by curly braces { and } in JSON), use JObject
  • If you know that you have an array or list (indicated by square brackets [ and ] ), use JArray
  • If you know you have a primitive value, use JValue
  • If you do not know which token you have, or want to be able to process any of the above methods, use JToken . Then you can check its Type property to determine what the token is and apply it accordingly.
+53
source

All Articles