TL; DR VersiónConversión de un JToken (o cadena) a un determinado tipo
Tengo un objeto de tipo JToken
(pero también puede ser un string
) y tengo que convertirlo en un tipo de contenido en la variable type
:
Type type = typeof(DateTime); /* can be any other Type like string, ulong etc */
var obj = jsonObject["date_joined"]; /* contains 2012-08-13T06:01:23Z+05:00 */
var result = Some_Way_To_Convert(type, obj);
lo anterior result
debe ser un objeto DateTime con el valor dado en date_joined
.
historia completa
estoy usando tanto RestSharp y Json.NET en un proyecto de Windows Phone y estoy atascado al intentar deserializar respuestas JSON de una API REST.
Lo que estoy tratando de lograr es escribir un método genérico que pueda mapear fácilmente mi respuesta JSON en mis entidades CLR, al igual que ya puede hacer con RestSharp. El único problema es que la implementación predeterminada de RestSharp no funciona para mí y no puede analizar correctamente el JSON ya que la respuesta no siempre devuelve todas las propiedades (no devuelvo campos que son null
del servidor REST).
Es por eso que decidí usar el Json.NET de Newtonsoft ya que tiene un motor deserializador Json mucho más potente. Desafortunadamente, no admite nombres de propiedades/campos difusos como RestSharp (o no he encontrado ninguno), por lo que tampoco se correlaciona correctamente con mis entidades CLR cuando uso algo como decir JsonConvert.DeserializeObject<User>(response.Content)
.
Aquí es lo que mi JSON se parece a (un ejemplo en realidad):
{
"id" : 77239923,
"username" : "UzEE",
"email" : "[email protected]",
"name" : "Uzair Sajid",
"twitter_screen_name" : "UzEE",
"join_date" : "2012-08-13T05:30:23Z05+00",
"timezone" : 5.5,
"access_token" : {
"token" : "nkjanIUI8983nkSj)*#)([email protected]",
"scope" : [ "read", "write", "bake pies" ],
"expires" : 57723
},
"friends" : [{
"id" : 2347484",
"name" : "Bruce Wayne"
},
{
"id" : 996236,
"name" : "Clark Kent"
}]
}
Y es un ejemplo de mis entidades CLR aquí:
class AccessToken
{
public string Token { get; set; }
public int Expires { get; set; }
public string[] Scope { get; set; }
public string Secret { get; set; } /* may not always be returned */
}
class User
{
public ulong Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public string TwitterScreenName { get; set; }
public DateTime JoinDate { get; set; }
public float Timezone { get; set; }
public bool IsOnline { get; set; } /* another field that might be blank e.g. */
public AccessToken AccessToken { get; set; }
public List<User> Friends { get; set; }
}
Lo que quiero es una forma sencilla de analizar los anteriores JSON en los objetos CLR dados. He buscado en el código fuente de RestSharp y he visto el código JsonDeserializer
y he podido escribir un método de extensión genérico DeserializeResponse<T>
en JObject
que debería devolver un objeto del tipo T
. El uso previsto es algo como esto:
var user = JObject.Parse(response.Content).DeserializeResponse<User>();
El método anterior se debe analizar la respuesta JSON dado a un objeto de entidad de usuario. He aquí un fragmento de código real de lo que estoy haciendo en el método DeserializeResponse<User>
extensión (su basado en el código RestSharp):
public static T DeserializeResponse<T>(this JObject obj) where T : new()
{
T result = new T();
var props = typeof(T).GetProperties().Where(p => p.CanWrite).ToList();
var objectDictionary = obj as IDictionary<string, JToken>;
foreach (var prop in props)
{
var name = prop.Name.GetNameVariants(CultureInfo.CurrentCulture).FirstOrDefault(n => objectDictionary.ContainsKey(n));
var value = name != null ? obj[name] : null;
if (value == null) continue;
var type = prop.PropertyType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = type.GetGenericArguments()[0];
}
// This is a problem. I need a way to convert JToken value into an object of Type type
prop.SetValue(result, ConvertValue(type, value), null);
}
return result;
}
supongo que la conversión debe ser una cosa muy fácil de hacer ya que es un trivial tarea. Pero he estado buscando desde hace bastante tiempo y todavía no he encontrado una manera de hacerlo a través de Json.NET (y seamos honestos, la documentación es un tanto comprensible y le faltan algunos ejemplos).
Cualquier ayuda sería realmente apreciada.
Cualquier ayuda aquí? Esta es la segunda vez que hago una pregunta sobre SO y, sin embargo, nunca recibí una respuesta:/ –
http://stackoverflow.com/questions/9589218/get-value-from-jtoken-that-may-not-exist- mejores prácticas – Guillaume
@Guillaume Gracias. Ya lo había leído antes de publicarlo. El problema es que estoy escribiendo un analizador que debería ser capaz de manejar cualquier valor que encuentre, por lo que un simple 'jToken.value()' no funcionará, ya que no sé que sería un 'doble'. No sé el tipo de antemano. –