restclient example deserialize async c# windows-phone-7 json.net restsharp

c# - example - Conversión de un JToken(o cadena) a un Tipo dado



restsharp timeout (4)

Versión TL; DR

Tengo un objeto de tipo JToken (pero también puede ser una string ) y necesito convertirlo en un tipo contenido en la variable de 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);

El result anterior debe ser un objeto DateTime con el valor dado en date_joined .

Historia completa

Estoy usando tanto RestSharp como Json.NET en un proyecto de Windows Phone y estoy atascado al tratar de deserializar las 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 puedes 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 desde el servidor REST).

Es por eso que decidí usar el Json.NET de Newtonsoft ya que tiene un motor deserializador Json mucho más poderoso. Desafortunadamente, no admite nombres de propiedad / campo difusos como RestSharp (o no he encontrado ninguno), por lo que tampoco se correlaciona correctamente con mis entidades CLR cuando uso algo como, por ejemplo, JsonConvert.DeserializeObject<User>(response.Content) .

Esto es lo que parece mi Json (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)*#)(kjb@K", "scope" : [ "read", "write", "bake pies" ], "expires" : 57723 }, "friends" : [{ "id" : 2347484", "name" : "Bruce Wayne" }, { "id" : 996236, "name" : "Clark Kent" }] }

Y aquí hay un ejemplo de mis entidades CLR:

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 el JSON anterior 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 de tipo T El uso previsto es algo como esto:

var user = JObject.Parse(response.Content).DeserializeResponse<User>();

El método anterior debe analizar la Respuesta Json dada a un objeto de entidad Usuario. Aquí hay un fragmento de código real de lo que estoy haciendo en el método de extensión DeserializeResponse<User> (está 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 debería ser una tarea realmente sencilla, ya que es una tarea trivial. 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.


Hay un método ToObject ahora.

var obj = jsonObject["date_joined"]; var result = obj.ToObject<DateTime>();

También funciona con cualquier tipo complejo y obedece a las reglas JsonPropertyAttribute

var result = obj.ToObject<MyClass>(); public class MyClass { [JsonProperty("date_field")] public DateTime MyDate {get;set;} }


Pude convertir utilizando el método siguiente para mi WebAPI:

[HttpPost] public HttpResponseMessage Post(dynamic item) // Passing parameter as dynamic { JArray itemArray = item["Region"]; // You need to add JSON.NET library JObject obj = itemArray[0] as JObject; // Converting from JArray to JObject Region objRegion = obj.ToObject<Region>(); // Converting to Region object }


System.Convert.ChangeType(jtoken.ToString(), targetType);

o

JsonConvert.DeserializeObject(jtoken.ToString(), targetType);

--EDITAR--

Uzair, aquí hay un ejemplo completo solo para mostrarte que funcionan

string json = @"{ ""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)*#)(kjb@K"", ""scope"" : [ ""read"", ""write"", ""bake pies"" ], ""expires"" : 57723 }, ""friends"" : [{ ""id"" : 2347484, ""name"" : ""Bruce Wayne"" }, { ""id"" : 996236, ""name"" : ""Clark Kent"" }] }"; var obj = (JObject)JsonConvert.DeserializeObject(json); Type type = typeof(int); var i1 = System.Convert.ChangeType(obj["id"].ToString(), type); var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type);


var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type);

arroja una excepción de análisis debido a las comillas faltantes alrededor del primer argumento (creo). Lo tengo que trabajar agregando las comillas:

var i2 = JsonConvert.DeserializeObject("/"" + obj["id"].ToString() + "/"", type);