TL; DR VersioneConversione di un JToken (o stringa) per un determinato tipo
Ho un oggetto di tipo JToken
(ma può anche essere un string
) e ho bisogno di convertirlo in un tipo di contenuto in la variabile 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);
Quanto sopra result
dovrebbe essere un oggetto DateTime con il valore riportato in date_joined
.
Full Story
sto utilizzando sia RestSharp e Json.NET in un progetto Windows Phone e mi sono bloccato durante il tentativo di deserializzare risposte JSON da un API REST.
Quello che sto effettivamente cercando di realizzare è scrivere un metodo generico che possa facilmente mappare la mia risposta JSON alle mie entità CLR, proprio come si fa già con RestSharp. L'unico problema è che l'implementazione RestSharp predefinita non funziona per me e non riesce a analizzare correttamente il JSON poiché la risposta non sempre restituisce tutte le proprietà (non restituisco i campi che sono null
dal server REST).
Ecco perché ho deciso di utilizzare Json.NET di Newtonsoft poiché ha un motore di deserializzazione Json molto più potente. Sfortunatamente, non supporta i nomi di proprietà/campi fuzzy come RestSharp (o non ne ho trovato nessuno), quindi non viene mappato correttamente alle entità CLR quando uso qualcosa come JsonConvert.DeserializeObject<User>(response.Content)
.
Ecco ciò che il mio JSON sembra (un esempio in realtà):
{
"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"
}]
}
Ed ecco un esempio dei miei soggetti 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; }
}
Quello che voglio è un modo semplice per analizzare quanto sopra JSON negli oggetti CLR dati. Ho esaminato il codice sorgente RestSharp e ho visto il codice JsonDeserializer
e sono stato in grado di scrivere un metodo di estensione generico DeserializeResponse<T>
su JObject
che dovrebbe restituire un oggetto di tipo T
. La destinazione d'uso è qualcosa di simile:
var user = JObject.Parse(response.Content).DeserializeResponse<User>();
Il metodo di cui sopra dovrebbe analizzare la data risposta JSON a un oggetto entità utente. Ecco un frammento di codice reale di quello che sto facendo nel metodo DeserializeResponse<User>
estensione (la sua base di codice 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;
}
Sto indovinando che la conversione dovrebbe essere una cosa davvero semplice da fare perché il suo un banale compito. Ma ho cercato un bel po 'di tempo e ancora non ho trovato il modo di farlo tramite Json.NET (e, a essere onesti, la documentazione è abbastanza per capire e manca qualche esempio).
Qualsiasi aiuto sarebbe davvero apprezzato.
Qualsiasi aiuto qui? Questa è la seconda volta che ho fatto qualsiasi domanda su SO e tuttavia non ho mai avuto una risposta:/ –
http://stackoverflow.com/questions/9589218/get-value-from-jtoken-that-may-not-exist- best practice – Guillaume
@Guillaume Grazie. L'avevo già letto prima di postare. Il problema è che sto scrivendo un parser che dovrebbe essere in grado di gestire qualsiasi valore incontrato così un semplice 'jToken.value()' non funzionerà dato che non so che sarebbe un 'double'. Non conosco il tipo prima mano. –