Konvertieren eines JToken (oder einer Zeichenfolge) in einen bestimmten Typ

TL; DR Version

Ich habe ein Objekt vom TypJToken (kann aber auch eine seinstring) und ich muss es in einen Typ konvertieren, der in dertype Variable:

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);

Obenstehendesresult sollte ein DateTime-Objekt mit dem in angegebenen Wert seindate_joined.

Ganze Geschichte

Ich verwende sowohl RestSharp als auch Json.NET in einem Windows Phone-Projekt und stecke fest, während ich versuche, JSON-Antworten von einer REST-API zu deserialisieren.

Eigentlich versuche ich, eine generische Methode zu schreiben, mit der ich meine JSON-Antwort auf einfache Weise meinen CLR-Entitäten zuordnen kann, so wie Sie es mit RestSharp bereits tun können. Das einzige Problem ist, dass die standardmäßige RestSharp-Implementierung bei mir nicht funktioniert und das JSON nicht erfolgreich analysiert werden kann, da die Antwort nicht immer alle Eigenschaften zurückgibt (ich gebe keine Felder zurück, die sind)null vom REST-Server).

Aus diesem Grund habe ich mich für Json.NET von Newtonsoft entschieden, da es über eine viel leistungsstärkere Json-Deserialisierungs-Engine verfügt. Leider werden Fuzzy-Eigenschafts- / Feldnamen wie "RestSharp" (oder "Ich habe keine gefunden") nicht unterstützt, sodass die Zuordnung zu meinen CLR-Entitäten auch nicht korrekt ist, wenn ich so etwas wie "say" verwendeJsonConvert.DeserializeObject<User>(response.Content).

So sieht mein Json aus (ein Beispiel):

{
    "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"
    }]
}

Und hier ist ein Beispiel für meine CLR-Entitäten:

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; }
}

Was ich möchte, ist eine einfache Möglichkeit, den obigen JSON in die angegebenen CLR-Objekte zu zerlegen. Ich habe mich im RestSharp-Quellcode umgesehen und das gesehenJsonDeserializer Code und ich war in der Lage, eine generische Erweiterungsmethode zu schreibenDeserializeResponse<T> aufJObject Das sollte ein Objekt vom Typ zurückgebenT. Der Verwendungszweck ist ungefähr so:

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

Die obige Methode sollte die angegebene Json-Antwort auf ein Benutzerentitätsobjekt analysieren. Ist hier ein tatsächlicher Codeausschnitt von, was ich im tueDeserializeResponse<User> Erweiterungsmethode (basiert auf RestSharp-Code):

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;
}

Ich vermute, dass die Konvertierung eine wirklich einfache Sache sein sollte, da es eine triviale Aufgabe ist. Aber ich habe schon eine ganze Weile gesucht und immer noch keine Möglichkeit gefunden, dies über Json.NET zu tun (und um ehrlich zu sein, die Dokumentation ist ein bisschen zu verständlich und es fehlen einige Beispiele).

Jede Hilfe wäre wirklich dankbar.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage