Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get value from JToken that may not exist (best practices)

Tags:

c#

json.net

People also ask

What is the difference between JToken and JObject?

So you see, a JObject is a JContainer , which is a JToken . Here's the basic rule of thumb: If you know you have an object (denoted by curly braces { and } in JSON), use JObject. If you know you have an array or list (denoted by square brackets [ and ] ), use JArray.

Is JToken a JArray?

As stated by dbc, a JToken that represent a JArray, is already a JArray. That is if the JToken. Type equals an JTokenType.

What does JToken parse do?

Parse() to parse a JSON string you know to represent an "atomic" value, requiring the use of JToken. Parse() in such a case. Similarly, JToken. FromObject() may be used to serialize any sort of c# object to a JToken hierarchy without needing to know in advance the resulting JSON type.


This is pretty much what the generic method Value() is for. You get exactly the behavior you want if you combine it with nullable value types and the ?? operator:

width = jToken.Value<double?>("width") ?? 100;

I would write GetValue as below

public static T GetValue<T>(this JToken jToken, string key, T defaultValue = default(T))
{
    dynamic ret = jToken[key];
    if (ret == null) return defaultValue;
    if (ret is JObject) return JsonConvert.DeserializeObject<T>(ret.ToString());
    return (T)ret;
}

This way you can get the value of not only the basic types but also complex objects. Here is a sample

public class ClassA
{
    public int I;
    public double D;
    public ClassB ClassB;
}
public class ClassB
{
    public int I;
    public string S;
}

var jt = JToken.Parse("{ I:1, D:3.5, ClassB:{I:2, S:'test'} }");

int i1 = jt.GetValue<int>("I");
double d1 = jt.GetValue<double>("D");
ClassB b = jt.GetValue<ClassB>("ClassB");

Here is how you can check if the token exists:

if (jobject["Result"].SelectToken("Items") != null) { ... }

It checks if "Items" exists in "Result".

This is a NOT working example that causes exception:

if (jobject["Result"]["Items"] != null) { ... }

You can simply typecast, and it will do the conversion for you, e.g.

var with = (double?) jToken[key] ?? 100;

It will automatically return null if said key is not present in the object, so there's no need to test for it.