Obtenga valor de JToken que puede no existir (mejores prácticas)
¿Cuál es la mejor práctica para recuperar valores JSON que pueden ni siquiera existir en C# usando Json.NET ?
Ahora mismo estoy tratando con un proveedor JSON que devuelve JSON que a veces contiene ciertos pares clave/valor, y a veces no lo hace. He estado usando (quizás incorrectamente) este método para obtener mis valores (ejemplo para obtener un doble):
if(null != jToken["width"])
width = double.Parse(jToken["width"].ToString());
else
width = 100;
Ahora eso funciona bien, pero cuando hay muchos de ellos es engorroso. Terminé escribiendo un método de extensión, y solo después de escribirlo me pregunté si tal vez estaba siendo estúpido... de todos modos, aquí está el método de extensión (solo incluyo casos para double y string, pero en realidad tengo bastantes más):
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;
}
Y aquí hay un ejemplo del uso del método de extensión:
width = jToken.GetValue<double>("width", 100);
Por cierto, Por favor perdone lo que puede ser una pregunta realmente tonta, ya que parece algo para lo que debería haber una función incorporada... Probé Google, y Json.NET documentación, sin embargo yo soy inepto en encontrar la solución a mi pregunta o no está claro en la documentación.
6 answers
Esto es más o menos lo que el método genérico Value()
es para. Obtendrá exactamente el comportamiento que desea si lo combina con tipos de valores nullables y el operador ??
:
width = jToken.Value<double?>("width") ?? 100;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 18:15:54
Escribiría GetValue
como a continuación
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 esta manera puede obtener el valor no solo de los tipos básicos, sino también de los objetos complejos. He aquí una muestra
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");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 20:47:47
Aquí es cómo puede comprobar si el token existe:
if (jobject["Result"].SelectToken("Items") != null) { ... }
Comprueba si "Items" existe en "Result".
Este es un ejemplo que no funciona que causa excepción:
if (jobject["Result"]["Items"] != null) { ... }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-01 18:45:25
Simplemente puede encasillar, y hará la conversión por usted, por ejemplo,
var with = (double?) jToken[key] ?? 100;
Devolverá automáticamente null
si dicha clave no está presente en el objeto, por lo que no hay necesidad de probarlo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-03 06:58:32
TYPE variable = jsonbody["key"]?.Value<TYPE>() ?? DEFAULT_VALUE;
Por ejemplo
bool attachMap = jsonbody["map"]?.Value<bool>() ?? false;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-30 15:50:14
Esto se encarga de nulls
var body = JObject.Parse("anyjsonString");
body?.SelectToken("path-string-prop")?.ToString();
body?.SelectToken("path-double-prop")?.ToObject<double>();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-05 04:09:08