[C#] Konvertieren eines JToken (oder einer Zeichenfolge) in einen bestimmten Typ


Answers

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

oder

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

--BEARBEITEN--

Uzair, Hier ist ein komplettes Beispiel, nur um Ihnen zu zeigen, dass sie arbeiten

string json = @"{
        ""id"" : 77239923,
        ""username"" : ""UzEE"",
        ""email"" : ""uzee@email.net"",
        ""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);
Question

TL; DR-Version

Ich habe ein Objekt vom Typ JToken (kann aber auch ein string ) und muss es in einen Typ konvertieren, der in der Typvariablen enthalten ist:

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

Das obige result sollte ein DateTime-Objekt mit dem in date_joined angegebenen Wert date_joined .

Ganze Geschichte

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

Was ich eigentlich erreichen möchte, ist, eine generische Methode zu schreiben, mit der ich meine JSON-Antwort leicht in meine CLR-Entitäten abbilden kann, ähnlich wie es bereits mit RestSharp möglich ist. Das einzige Problem ist, dass die standardmäßige RestSharp-Implementierung für mich 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 vom REST-Server null sind).

Darum entschied ich mich für Newtonsofts Json.NET, da es eine viel leistungsfähigere Json Deserialisierungs-Engine hat. Unglücklicherweise unterstützt es keine Fuzzy-Eigenschaften / Feldnamen wie RestSharp (oder ich habe keine gefunden), so dass es auch nicht korrekt zu meinen CLR-Entitäten zugeordnet wird, wenn ich etwas verwende, wie zum Beispiel JsonConvert.DeserializeObject<User>(response.Content) .

So sieht mein Json aus (ein Beispiel):

{
    "id" : 77239923,
    "username" : "UzEE",
    "email" : "uzee@email.net",
    "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, die obige JSON in die angegebenen CLR-Objekte zu zerlegen. Ich habe mir den RestSharp-Quellcode angesehen und den JsonDeserializer Code gesehen, und ich konnte eine generische Erweiterungsmethode DeserializeResponse<T> auf JObject , die ein Objekt vom Typ T . Der Verwendungszweck ist ungefähr so:

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

Die obige Methode sollte die angegebene Json-Antwort auf ein Entity-Objekt des Benutzers analysieren. Hier ist ein Codefragment davon, was ich in der Erweiterungsmethode " DeserializeResponse<User> " (basierend auf RestSharp-Code) mache:

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 sie eine triviale Aufgabe ist. Aber ich habe schon eine ganze Weile gesucht und immer noch keinen Weg gefunden, es über Json.NET zu tun (und seien wir ehrlich, die Dokumentation ist irgendwie zu verstehen und es fehlen einige Beispiele).

Jede Hilfe wäre wirklich willkommen.




Ich konnte mit der folgenden Methode für meine WebAPI konvertieren:

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