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.
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;
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");
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) { ... }
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.
Cela prend soin des NULL
var body = JObject.Parse("anyjsonString");
body?.SelectToken("path-string-prop")?.ToString();
body?.SelectToken("path-double-prop")?.ToObject<double>();
TYPE variable = jsonbody["key"]?.Value<TYPE>() ?? DEFAULT_VALUE;
par exemple.
bool attachMap = jsonbody["map"]?.Value<bool>() ?? false;