I am having trouble understanding when to use JContainer
, JObject
, and JToken
. I understand from the "standards" that JObject
is composed of JProperties
and that JToken
is the base abstract class for all of the 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'm deserializing that file's contents successfully using this statement:
string json; using (StreamReader reader = new StreamReader(@"myjsonfile.json")) { json = reader.ReadToEnd(); }
At that point, I take the JSON string object and deserialize it to a JObject
(and this might be my mistake--perhaps I need to make jsonWork
a 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 look similar to this:
{ "Object1" : { ... }, "Object2" : { ... }, "Object3" : { ... } }
Each object is composed of all sorts of tokens (arrays, strings, other objects, etc.), so it is dynamic JSON. (I used ellipses as placeholders rather than muddying up this question wit lots of JSON data.)
I want to process "Object1"
, "Object2"
, and "Object3"
separately using LINQ, however. So, 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 fail.
I used var
above because I have no idea what object type I should be using: JContainer
, JObject
, or JToken
! Just so you know what I want to do, once the above jsonObject#
variables are properly assigned, I would like to use LINQ to query the JSON they contain. Here is a very simple example:
var query = from p in jsonObject1 where p.Name == "Name1" select p
Of course, my LINQ ultimately will filter for JSON arrays, objects, strings, etc., in the jsonObject
variable. I think once I get going, I can use LinqPad to help me filter the JSON using LINQ.
I discovered that if I use:
// this line WORKS var jsonObject1 = ((JObject)jsonWork).["Object1"];
Then I get an JObject
type in jsonObject1
. Is this the correct approach?
It is unclear to me when/why one would use JContainer
when it seems that JToken
and JObject
objects work with LINQ quite well. What is the purpose of JContainer
?
JToken is the base class for all JSON elements. You should just use the Parse method for the type of element you expect to have in the string. If you don't know what it is, use JToken, and then you'll be able to down cast it to JObject, JArray, etc. In this case you always expect a JObject, so use that.
JObject. It represents a JSON Object. It helps to parse JSON data and apply querying (LINQ) to filter out required data. It is presented in Newtonsoft.
JToken is the abstract base class of JObject , JArray , JProperty , and JValue , which represent pieces of JSON data after they have been parsed. JsonToken is an enum that is used by JsonReader and JsonWriter to indicate which type of token is being read or written.
Represents a token that can contain other tokens. Newtonsoft.Json.Linq. JToken.
You don't really need to worry about JContainer
in most cases. It is there to help organize and structure LINQ-to-JSON into well-factored code.
The JToken
hierarchy looks like this:
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, a JObject
is a JContainer
, which is a JToken
.
Here's the basic rule of thumb:
{
and }
in JSON), use JObject
[
and ]
), use JArray
JValue
JToken
. You can then check its Type
property to determine what kind of token it is and cast it appropriately.JContainer
is a base class for JSON elements that have child items. JObject
, JArray
, JProperty
and JConstructor
all inherit from it.
For example, the following code:
(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")
Would throw an InvalidCastException
, but if you cast it to a JContainer
, it would be fine.
Regarding your original question, if you know you have a JSON object at the top level, you can just use:
var jsonWork = JObject.Parse(json); var jsonObject1 = jsonWork["Object1"];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With