Désérialiser JSON avec C #


206

J'essaie de désérialiser l' appel d' API Graph d' un ami Facebook dans une liste d'objets. L'objet JSON ressemble à:

{"data":[{"id":"518523721","name":"ftyft"},
         {"id":"527032438","name":"ftyftyf"},
         {"id":"527572047","name":"ftgft"},
         {"id":"531141884","name":"ftftft"},
         {"id":"532652067","name"...

List<EFacebook> facebooks = new JavaScriptSerializer().Deserialize<List<EFacebook>>(result);

Cela ne fonctionne pas, car l'objet primitif n'est pas valide. Comment puis-je désérialiser cela?


3
écrire un désérialiseur personnalisé spécifiquement pour répondre à un tel json ...
ashutosh raina

2
ou vous pouvez utiliser un Dictionary<string,string>, consultez: stackoverflow.com/questions/7699972/…
Kakashi

9
Votre ami: json2csharp.com
nawfal

4
En fait, les studios visuels (à partir de 2013 ou 2012 avec des outils Web installés) ont cette fonctionnalité exacte intégrée: Édition> Collage spécial> Collage JSON en tant que classes
floomby

Réponses:


264

Vous devez créer une structure comme celle-ci:

public class Friends
{

    public List<FacebookFriend> data {get; set;}
}

public class FacebookFriend
{

    public string id {get; set;}
    public string name {get; set;}
}

Ensuite, vous devriez pouvoir faire:

Friends facebookFriends = new JavaScriptSerializer().Deserialize<Friends>(result);

Les noms de mes classes ne sont qu'un exemple. Vous devez utiliser des noms propres.

Ajout d'un exemple de test:

string json =
    @"{""data"":[{""id"":""518523721"",""name"":""ftyft""}, {""id"":""527032438"",""name"":""ftyftyf""}, {""id"":""527572047"",""name"":""ftgft""}, {""id"":""531141884"",""name"":""ftftft""}]}";

Friends facebookFriends = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Friends>(json);

foreach(var item in facebookFriends.data)
{
    Console.WriteLine("id: {0}, name: {1}", item.id, item.name);
}

Produit:

id: 518523721, name: ftyft
id: 527032438, name: ftyftyf
id: 527572047, name: ftgft
id: 531141884, name: ftftft

3
Ouais, c'est ce que je ne veux pas faire, créez un nouvel objet pour tenir les enfants. Je pense que je vais sous-chaîne le json prenant l'objet primitif. Je vous remercie.

@Kevin Holditch merci pour la correction. J'ai raté un élément important :)
Icare

2
Ce que je n'aime pas dans ce System.Web.Script.Serialization.JavaScriptSerializer (), c'est que vous avez toujours besoin d'un type défini T. En Java, il y a cette bibliothèque org.java (package) qui reste tout anonyme: "JSONObject [" param "]. JSONarray (5)" etc
sports

2
Il est important de noter que les paramètres des propriétés id et name doivent être rendus publics. S'ils sont définis sur privé ou protégé, la désérialisation s'exécutera sans erreur mais toutes les données seront nulles.
Isaac Zais

2
@sports, vous pouvez le faire en C # en désérialisant vers une dynamique, mais les performances sont bien meilleures si vous désérialisez vers un type connu.
PRMan

50

Parfois, je préfère les objets dynamiques:

public JsonResult GetJson()
{
  string res;
  WebClient client = new WebClient();

  // Download string
  string value = client.DownloadString("https://api.instagram.com/v1/users/000000000/media/recent/?client_id=clientId");

  // Write values
  res = value;
  dynamic dyn = JsonConvert.DeserializeObject(res);
  var lstInstagramObjects = new List<InstagramModel>();

  foreach(var obj in dyn.data)
  {
    lstInstagramObjects.Add(new InstagramModel()
    {
      Link = (obj.link != null) ? obj.link.ToString() : "",
      VideoUrl = (obj.videos != null) ? obj.videos.standard_resolution.url.ToString() : "",
      CommentsCount = int.Parse(obj.comments.count.ToString()),
      LikesCount = int.Parse(obj.likes.count.ToString()),
      CreatedTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds((double.Parse(obj.created_time.ToString()))),
      ImageUrl = (obj.images != null) ? obj.images.standard_resolution.url.ToString() : "",
      User = new InstagramModel.UserAccount()
             {
               username = obj.user.username,
               website = obj.user.website,
               profile_picture = obj.user.profile_picture,
               full_name = obj.user.full_name,
               bio = obj.user.bio,
               id = obj.user.id
             }
    });
  }

  return Json(lstInstagramObjects, JsonRequestBehavior.AllowGet);
}

Un exemple d'une instance où cela a été utile était lorsque l'objet dans lequel j'essayais de désérialiser contenait une propriété qui était une interface
soupy1976

2
Une explication serait de mise.
Peter Mortensen

Pourquoi préférez-vous cela à la réponse acceptée par @Icarus?
Interrogatoire du

@Questioning, la désérialisation vers des classes de types forts négligerait toutes les propriétés qui n'étaient pas dans vos classes, tandis que la désérialisation vers des objets dynamiques renverrait simplement un objet .Net dynamique qui est flexible pour toute nouvelle propriété créée à l'avenir sans avoir à mettre à jour vos classes. (comme je l'ai dit, parfois pas standard)
Bishoy Hanna

39

Un excellent moyen de générer automatiquement ces classes pour vous est de copier votre sortie JSON et de la jeter ici:

http://json2csharp.com/

Il vous fournira un point de départ pour retoucher vos classes pour la désérialisation.


28

Très facilement, nous pouvons analyser le contenu JSON à l'aide du dictionnaire et de JavaScriptSerializer. Voici l'exemple de code par lequel j'analyse le contenu JSON d'un fichier ashx.

var jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();
Dictionary<string, string> sData = jss.Deserialize<Dictionary<string, string>>(json);
string _Name = sData["Name"].ToString();
string _Subject = sData["Subject"].ToString();
string _Email = sData["Email"].ToString();
string _Details = sData["Details"].ToString();

3
Cette solution est très utile si vous n'avez pas le temps ou si vous avez besoin de créer des contrats de données. Surtout si vous n'êtes intéressé que par quelques attributs profondément enfouis dans la structure JSON. Dans cette situation, vous pouvez utiliser une série d'instructions pour naviguer vers ce dont vous avez besoin. Remarque: le type à désérialiser peut également être l'un des suivants: Dictionary <chaîne, objet> ou ArrayList (lorsqu'un nœud a une structure répétitive).
Philippe Monnet

1
J'obtiens une exception d'exécution avec ceci: Aucun constructeur sans paramètre défini pour le type de 'System.String' sur la ligne de code Deserialize.
RSK

20

Newtonsoft.JSONest une bonne solution pour ce genre de situations. Aussi Newtonsof.JSONest plus rapide que d' autres, comme JavaScriptSerializer, DataContractJsonSerializer.

Dans cet exemple, vous pouvez effectuer les opérations suivantes:

var jsonData = JObject.Parse("your JSON data here");

Ensuite, vous pouvez convertir jsonData en JArray, et vous pouvez utiliser une forboucle pour obtenir des données à chaque itération.

Aussi, je veux ajouter quelque chose:

for (int i = 0; (JArray)jsonData["data"].Count; i++)
{
    var data = jsonData[i - 1];
}

Travailler avec un objet dynamique et utiliser la sérialisation Newtonsoft est un bon choix.


15

Je suis d'accord avec Icarus (j'aurais commenté si je pouvais), mais au lieu d'utiliser une classe CustomObject , j'utiliserais un dictionnaire (au cas où Facebook ajouterait quelque chose).

private class MyFacebookClass
{
    public IList<IDictionary<string, string>> data { get; set; }
}

ou

private class MyFacebookClass
{
    public IList<IDictionary<string, object>> data { get; set; }
}

3
L'utilisation dynamique fonctionne mieux dans les nouvelles versions. public IList<IDictionary<string, dynmaic>> data { get; set; }
BJury

3

Sérialisation:

// Convert an object to JSON string format
string jsonData = JsonConvert.SerializeObject(obj);

Response.Write(jsonData);

Désérialisation ::

Pour désérialiser un objet dynamique

  string json = @"{
      'Name': 'name',
      'Description': 'des'
    }";

var res = JsonConvert.DeserializeObject< dynamic>(json);

Response.Write(res.Name);

3

Vous pouvez utiliser ces extensions

public static class JsonExtensions
{
   public static T ToObject<T>(this string jsonText)
   {
       return JsonConvert.DeserializeObject<T>(jsonText);
   }

   public static string ToJson<T>(this T obj)
   {
       return JsonConvert.SerializeObject(obj);
   }
}


1

Si vous utilisez .NET Core 3.0, vous pouvez utiliser System.Text.Json (qui est maintenant intégré) pour désérialiser JSON.

La première étape consiste à créer des classes pour modéliser le JSON. Il existe de nombreux outils qui peuvent vous y aider, et certaines des réponses ici les énumèrent.

Certaines options sont http://json2csharp.com , http://app.quicktype.io , ou utilisez Visual Studio (menu EditionCollage spécialColler JSON comme classes ).

public class Person
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Response
{
    public List<Person> Data { get; set; }
}

Ensuite, vous pouvez désérialiser en utilisant:

var people = JsonSerializer.Deserialize<Response>(json);

Si vous devez ajouter des paramètres, tels que la camelCasegestion, passez les paramètres du sérialiseur dans le désérialiseur comme ceci:

var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var person = JsonSerializer.Deserialize<Response>(json, options);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.