TL; version DR
J’ai un object de type JToken
(mais peut aussi être une ssortingng
) et je dois le convertir en un type contenu dans la variable de type
:
Type type = typeof(DateTime); /* can be any other Type like ssortingng, ulong etc */ var obj = jsonObject["date_joined"]; /* contains 2012-08-13T06:01:23Z+05:00 */ var result = Some_Way_To_Convert(type, obj);
Le result
ci-dessus doit être un object DateTime avec la valeur donnée dans date_joined
.
Histoire complète
J’utilise à la fois RestSharp et Json.NET dans un projet Windows Phone et je suis coincé en essayant de désérialiser les réponses JSON à partir d’une API REST.
Ce que j’essaie de faire, c’est d’écrire une méthode générique qui peut facilement mapper ma réponse JSON dans mes entités CLR, comme vous pouvez déjà le faire avec RestSharp. Le seul problème est que l’implémentation par défaut de RestSharp ne fonctionne pas pour moi et que l’parsing du JSON échoue car la réponse ne retourne pas toujours toutes les propriétés (je ne renvoie pas les champs null
du serveur REST).
C’est pourquoi j’ai décidé d’utiliser Json.NET de Newtonsoft car il dispose d’un moteur de désérialisation Json beaucoup plus puissant. Malheureusement, il ne supporte pas les noms de propriétés / champs flous comme RestSharp (ou je n’en ai pas trouvé), donc il ne correspond pas correctement à mes entités CLR lorsque j’utilise quelque chose comme JsonConvert.DeserializeObject(response.Content)
.
Voici à quoi ressemble mon Json (un exemple en fait):
{ "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" }] }
Et voici un exemple de mes entités CLR:
class AccessToken { public ssortingng Token { get; set; } public int Expires { get; set; } public ssortingng[] Scope { get; set; } public ssortingng Secret { get; set; } /* may not always be returned */ } class User { public ulong Id { get; set; } public ssortingng UserName { get; set; } public ssortingng Email { get; set; } public ssortingng Name { get; set; } public ssortingng TwitterScreenName { get; set; } public DateTime JoinDate { get; set; } public float Timezone { get; set; } public bool IsOnline { get; set; } /* another field that might be blank eg */ public AccessToken AccessToken { get; set; } public List Friends { get; set; } }
Ce que je veux, c’est un moyen simple d’parsingr le JSON ci-dessus dans les objects CLR donnés. J’ai regardé autour du code source RestSharp et j’ai vu le code JsonDeserializer
et j’ai pu écrire une méthode d’extension générique DeserializeResponse
sur JObject
qui devrait renvoyer un object de type T
L’utilisation prévue est quelque chose comme ceci:
var user = JObject.Parse(response.Content).DeserializeResponse();
La méthode ci-dessus devrait parsingr la réponse Json donnée à un object entité utilisateur. Voici un extrait de code de ce que je fais dans la méthode d’extension DeserializeResponse
(basée sur le code RestSharp):
public static T DeserializeResponse(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; 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; }
Je devine que la conversion devrait être une chose très simple à faire puisque c’est une tâche sortingviale. Mais je recherche depuis un bon moment et je n’ai toujours pas trouvé le moyen de le faire via Json.NET (et soyons honnêtes, la documentation est un peu à la fois compréhensible et manque d’exemples).
Toute aide serait vraiment appréciée.
Il y a une méthode ToObject maintenant.
var obj = jsonObject["date_joined"]; var result = obj.ToObject();
Il fonctionne également avec tout type complexe et obéit aux règles JsonPropertyAtsortingbute
var result = obj.ToObject(); public class MyClass { [JsonProperty("date_field")] public DateTime MyDate {get;set;} }
System.Convert.ChangeType(jtoken.ToSsortingng(), targetType);
ou
JsonConvert.DeserializeObject(jtoken.ToSsortingng(), targetType);
–MODIFIER–
Uzair, Voici un exemple complet pour vous montrer qu’ils travaillent
ssortingng 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"].ToSsortingng(), type); var i2 = JsonConvert.DeserializeObject(obj["id"].ToSsortingng(), type);
var i2 = JsonConvert.DeserializeObject(obj["id"].ToSsortingng(), type);
jette une exception d’parsing due à des guillemets manquants autour du premier argument (je pense). Je l’ai fait fonctionner en ajoutant les citations:
var i2 = JsonConvert.DeserializeObject("\"" + obj["id"].ToSsortingng() + "\"", type);
J’ai pu convertir en utilisant la méthode ci-dessous pour mon 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(); // Converting to Region object }