web-dev-qa-db-fra.com

Désérialisation de JSON en un objet avec Json.NET

Je joue un peu avec le nouveau StackOverflow API . Malheureusement, mon JSON est un peu faible, j'ai donc besoin d'aide.

J'essaie de désérialiser ce JSON d'un utilisateur:

  {"user":{
    "user_id": 1,
    "user_type": "moderator",
    "creation_date": 1217514151,
    "display_name": "Jeff Atwood",
    ...
    "accept_rate": 100
  }}

dans un objet que j'ai décoré avec des attributs JsonProperty:

[JsonObject(MemberSerialization.OptIn)]
public class User
{
    [JsonProperty("user_id", Required = Required.Always)]        
    public virtual long UserId { get; set; }

    [JsonProperty("display_name", Required = Required.Always)]
    public virtual string Name { get; set; }

    ...
}

J'obtiens l'exception suivante:

Newtonsoft.Json.JsonSerializationException: propriété obligatoire 'id_utilisateur' introuvable dans JSON.

Est-ce parce que l'objet JSON est un tableau? Si oui, comment puis-je le désérialiser en un seul objet utilisateur?

Merci d'avance!

25
Igal Tabachnik

Comme Alexandre Jasmin l'a dit dans les commentaires de votre question, le JSON résultant a un wrapper autour de l'objet User que vous essayez de désérialiser.

Une solution de contournement consisterait à avoir dit classe wrapper:

public class UserResults
{
    public User user { get; set; }
}

Ensuite, la désérialisation fonctionnera:

using (var sr = new StringReader(json))
using (var jr = new JsonTextReader(sr))
{
    var js = new JsonSerializer();
    var u = js.Deserialize<UserResults>(jr);
    Console.WriteLine(u.user.display_name);
}

Il y aura de futures propriétés de métadonnées sur ce wrapper, par exemple horodatage de la réponse, donc ce n'est pas une mauvaise idée de l'utiliser!

27
Jarrod Dixon

Si vous ne souhaitez pas créer de classe wrapper, vous pouvez également accéder à l'utilisateur de cette façon:

String jsonString = "{\"user\":{\"user_id\": 1, \"user_type\": \"moderat...";
JToken root = JObject.Parse(jsonString);
JToken user = root["user"];
User deserializedUser = JsonConvert.DeserializeObject<User>(user.ToString());

Voir cette page dans la doc Json.NET pour plus de détails.

36
Alex Jasmin

Semblable à @Alexandre Jasmin réponse , vous pouvez utiliser un intermédiaire JsonSerializer pour convertir au lieu d'utiliser le haut niveau JsonConvert sur .ToString(). Aucune idée si c'est plus efficace ...

Références:

Exemple:

var root = JObject.Parse(jsonString);
var serializer = new JsonSerializer();
var expectedUserObject = serializer.Deserialize<User>(root["user"].CreateReader());
5
drzaus