web-dev-qa-db-fra.com

Obtenez de JToken une valeur qui peut ne pas exister (meilleures pratiques)

Quelle est la meilleure pratique pour récupérer des valeurs JSON qui peuvent même ne pas exister en C # en utilisant Json.NET ?

À l’heure actuelle, j’ai affaire à un fournisseur JSON qui renvoie un JSON contenant parfois certaines paires clé/valeur, et parfois non. J'ai utilisé (peut-être incorrectement) cette méthode pour obtenir mes valeurs (exemple pour obtenir un double):

if(null != jToken["width"])
    width = double.Parse(jToken["width"].ToString());
else
    width = 100;

Maintenant, cela fonctionne bien, mais quand il y en a beaucoup, c'est lourd. J'ai fini par écrire une méthode d'extension, et seulement après en l'écrivant, je me suis demandé si j'étais peut-être stupide ... en tout cas, voici la méthode de l'extension (j'inclue uniquement les cas de double et string, mais en réalité, j'en ai encore un peu):

public static T GetValue<T>(this JToken jToken, string key,
                            T defaultValue = default(T))
{
    T returnValue = defaultValue;

    if (jToken[key] != null)
    {
        object data = null;
        string sData = jToken[key].ToString();

        Type type = typeof(T);

        if (type is double)
            data = double.Parse(sData);
        else if (type is string)
            data = sData;

        if (null == data && type.IsValueType)
            throw new ArgumentException("Cannot parse type \"" + 
                type.FullName + "\" from value \"" + sData + "\"");

        returnValue = (T)Convert.ChangeType(data, 
            type, CultureInfo.InvariantCulture);
    }

    return returnValue;
}

Et voici un exemple d'utilisation de la méthode d'extension:

width = jToken.GetValue<double>("width", 100);

BTW, S'il vous plaît pardonnez ce qui peut être une question vraiment stupide, car il semble que quelque chose devrait y avoir une fonction intégrée pour ... J'ai essayé Google, et Json.NET documentation, mais je suis soit inapte à trouver la solution à ma question, soit ce n'est pas clair dans la documentation.

102
Paul Hazen

C'est à peu près ce que la méthode générique Value() est pour. Vous obtenez exactement le comportement souhaité si vous le combinez avec les types de valeur nullable et le ?? opérateur:

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

J'écrirais GetValue comme ci-dessous

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;
}

De cette façon, vous pouvez obtenir la valeur non seulement des types de base, mais également des objets complexes. Voici un échantillon

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");
17
L.B

Voici comment vous pouvez vérifier si le jeton existe:

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

Il vérifie si "Articles" existe dans "Résultat".

Ceci n'est pas un exemple fonctionnel qui provoque une exception:

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

Vous pouvez simplement dactylographier et il effectuera la conversion pour vous, par exemple.

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

Il retournera automatiquement null si ladite clé n'est pas présente dans l'objet, il n'est donc pas nécessaire de la tester.

3

Cela prend soin des NULL

var body = JObject.Parse("anyjsonString");

body?.SelectToken("path-string-prop")?.ToString();

body?.SelectToken("path-double-prop")?.ToObject<double>();
1
Max

TYPE variable = jsonbody["key"]?.Value<TYPE>() ?? DEFAULT_VALUE;

par exemple.

bool attachMap = jsonbody["map"]?.Value<bool>() ?? false;

1
Downhillski