330 votes

Désérialisation de JSON en objet .NET à l'aide de Newtonsoft (ou LINQ to JSON peut-être ?)

Je sais qu'il y a quelques messages sur Newtonsoft, alors j'espère que ce n'est pas une répétition... J'essaie de convertir les données JSON renvoyées par l'API de Kazaa en une sorte d'objet sympa.

WebClient client = new WebClient();
Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
StreamReader reader = new StreamReader(stream);

List<string> list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(reader.Read().ToString());

foreach (string item in list)
{
    Console.WriteLine(item);
}

//Console.WriteLine(reader.ReadLine());
stream.Close();

Cette ligne JsonConvert est juste la plus récente que j'ai essayée... Je n'ai pas tout compris et j'espérais éliminer certains problèmes en vous demandant votre avis. A l'origine, j'essayais de le convertir en un dictionnaire ou quelque chose comme ça... et en fait, j'ai juste besoin de saisir quelques valeurs là-dedans, donc à en juger par la documentation, peut-être que LINQ to JSON de Newtonsoft serait un meilleur choix ? Réflexions/Liens ?

Voici un exemple de données de retour JSON :

{
  "page": 1,
  "total_pages": 8,
  "total_entries": 74,
  "q": "muse",
  "albums": [
    {
      "name": "Muse",
      "permalink": "Muse",
      "cover_image_url": "http://image.kazaa.com/images/69/01672812 1569/Yaron_Herman_Trio/Muse/Yaron_Herman_Trio-Muse_1.jpg",
      "id": 93098,
      "artist_name": "Yaron Herman Trio"
    },
    {
      "name": "Muse",
      "permalink": "Muse",
      "cover_image_url": "htt p://image.kazaa.com/images/54/888880301154/Candy_Lo/Muse/Candy_Lo-Muse_1.jpg",
      "i d": 102702,
      "artist_name": "\u76e7\u5de7\u97f3"
    },
    {
      "name": "Absolution",
      "permalink": " Absolution",
      "cover_image_url": "http://image.kazaa.com/images/65/093624873365/Mus e/Absolution/Muse-Absolution_1.jpg",
      "id": 48896,
      "artist_name": "Muse"
    },
    {
      "name": "Ab solution",
      "permalink": "Absolution-2",
      "cover_image_url": "http://image.kazaa.com/i mages/20/825646911820/Muse/Absolution/Muse-Absolution_1.jpg",
      "id": 118573,
      "artist _name": "Muse"
    },
    {
      "name": "Black Holes And Revelations",
      "permalink": "Black-Holes-An d-Revelations",
      "cover_image_url": "http://image.kazaa.com/images/66/093624428466/ Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1.jpg",
      "id": 48813,
      "artist_name": "Muse"
    },
    {
      "name": "Black Holes And Revelations",
      "permalink": "Bla ck-Holes-And-Revelations-2",
      "cover_image_url": "http://image.kazaa.com/images/86/ 825646911486/Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1 .jpg",
      "id": 118543,
      "artist_name": "Muse"
    },
    {
      "name": "Origin Of Symmetry",
      "permalink": "Origin-Of-Symmetry",
      "cover_image_url": "http://image.kazaa.com/images/29/825646 912629/Muse/Origin_Of_Symmetry/Muse-Origin_Of_Symmetry_1.jpg",
      "id": 120491,
      "artis t_name": "Muse"
    },
    {
      "name": "Showbiz",
      "permalink": "Showbiz",
      "cover_image_url": "http: //image.kazaa.com/images/68/825646182268/Muse/Showbiz/Muse-Showbiz_1.jpg",
      "id": 60444,
      "artist_name": "Muse"
    },
    {
      "name": "Showbiz",
      "permalink": "Showbiz-2",
      "cover_imag e_url": "http://image.kazaa.com/images/50/825646912650/Muse/Showbiz/Muse-Showbiz_ 1.jpg",
      "id": 118545,
      "artist_name": "Muse"
    },
    {
      "name": "The Resistance",
      "permalink": "T he-Resistance",
      "cover_image_url": "http://image.kazaa.com/images/36/825646864836/ Muse/The_Resistance/Muse-The_Resistance_1.jpg",
      "id": 121171,
      "artist_name": "Muse"
    }
  ],
  "per_page": 10
}

J'ai lu un peu plus et j'ai découvert que le LINQ to JSON de Newtonsoft est exactement ce que je voulais... en utilisant WebClient, Stream, StreamReader et Newtonsoft... je peux aller chercher des données JSON chez Kazaa, extraire une URL, télécharger le fichier et faire tout cela en sept lignes de code ! J'adore ça.

WebClient client = new WebClient();
Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
StreamReader reader = new StreamReader(stream);

Newtonsoft.Json.Linq.JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());

// Instead of WriteLine, 2 or 3 lines of code here using WebClient to download the file
Console.WriteLine((string)jObject["albums"][0]["cover_image_url"]);
stream.Close();

Cet article reçoit tellement de visites que j'ai pensé qu'il serait utile d'inclure les éléments "d'utilisation" qui sont discutés dans les commentaires.

using(var client = new WebClient())
using(var stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album"))
using (var reader = new StreamReader(stream))
{
    var jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
    Console.WriteLine((string) jObject["albums"][0]["cover_image_url"]);
}

7 votes

Un bon exemple, merci. Juste une suggestion : vous l'avez peut-être laissé de côté par souci de concision, mais puisque WebClient , Stream y StreamReader tous les outils IDisposable vous pourriez ajouter des using à votre code.

0 votes

Ah oui, bien vu...(en fait, c'était juste une application de console que je lançais rapidement pour faire des recherches pour les tâches que j'ai à faire). Maintenant, je vais chercher la dernière pièce du puzzle, le cryptage HLS+AES :) ugh...lol

0 votes

La solution de Newtonsoft ne désérialise-t-elle pas complètement le JSON ? Tout comme la solution de @arcain.

278voto

biofractal Points 3907

Vous pouvez utiliser l'outil C# dynamic pour faciliter les choses. Cette technique simplifie également la refonte, car elle ne repose pas sur des chaînes de caractères magiques.

JSON

La chaîne JSON ci-dessous est une réponse simple provenant d'un appel API HTTP, et elle définit deux propriétés : Id y Name .

{"Id": 1, "Name": "biofractal"}

C#

Utilice JsonConvert.DeserializeObject<dynamic>() pour désérialiser cette chaîne en un type dynamique, puis accéder simplement à ses propriétés de la manière habituelle.

dynamic results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;

Si vous spécifiez le type de l results comme dynamic au lieu d'utiliser l'option var les valeurs de la propriété seront correctement désérialisées, par ex. Id à un int et non un JValue (merci à GFoley83 pour le commentaire ci-dessous).

Note : Le lien NuGet pour l'assemblage Newtonsoft est le suivant http://nuget.org/packages/newtonsoft.json .

Paquet : Vous pouvez également ajouter le paquet avec l'installateur nuget live, avec votre projet ouvert, faites simplement . parcourir le paquet et ensuite l'installer simplement installer, désinstaller, mettre à jour il sera simplement ajouté à votre projet sous Dependencies/NuGet.

0 votes

J'utilisais le même morceau de code que ci-dessus pour désérialiser la réponse twitter avec newtonsoft.dll version 4.5.6 et cela fonctionnait bien ... mais après l'avoir mis à jour à la version 5.0.6 ... il a commencé à lancer des erreurs ... une idée de la raison ? ?

1 votes

Bon pour les objets dynamiques ,quand on sait ou on a une classe c# donc on peut consommer comme une classe C# en remplacement de dynamique par exemple <Myclass>.

2 votes

Utilice dynamic results = JsonConvert.DeserializeObject<ExpandoObject>(json); ici FTW. Il va correctement désérialiser Id à un int et non à un JValue . Voir ici : dotnetfiddle.net/b0WxGJ

273voto

arcain Points 7152

Si vous n'avez besoin que d'obtenir quelques éléments de l'objet JSON, j'utiliserais LINQ to JSON de Json.NET. JObject classe. Par exemple :

JToken token = JObject.Parse(stringFullOfJson);

int page = (int)token.SelectToken("page");
int totalPages = (int)token.SelectToken("total_pages");

J'aime cette approche parce que vous n'avez pas besoin de désérialiser complètement l'objet JSON. C'est très pratique avec les API qui peuvent parfois vous surprendre avec des propriétés d'objet manquantes, comme Twitter.

Documentation : Sérialisation et désérialisation de JSON avec Json.NET y LINQ to JSON avec Json.NET

1 votes

Oui, j'ai lu et testé un peu plus... j'ai trouvé que c'était une bonne façon de faire... Newtonsoft, une belle bibliothèque, je vais poster mon exemple pour les autres...

1 votes

J'ai posté un exemple approximatif de la façon dont je le faisais... pas tout à fait la même chose, je vois que vous avez suggéré JToken.Parse... je ne suis pas encore sûr des différences entre les deux mais oui, c'est bien !

1 votes

@Jbenjamin Merci ! C'était une faute de frappe. JToken est la classe de base de JObject, et c'est juste ma préférence personnelle de travailler avec le type plus abstrait. Merci d'avoir attiré mon attention sur ce point.

45voto

Avec le dynamic il devient très facile d'analyser tout objet de ce type :

dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
var page = x.page;
var total_pages = x.total_pages
var albums = x.albums;
foreach(var album in albums)
{
    var albumName = album.name;

    // Access album data;
}

0 votes

Je voulais savoir comment boucler les résultats et cela a pris beaucoup trop de temps à trouver... merci !

22voto

Goku Points 200

Si, comme moi, vous préférez traiter des objets fortement typés**, optez pour :

MyObj obj =  JsonConvert.DeserializeObject<MyObj>(jsonString);

De cette façon, vous pouvez utiliser intellisense et la vérification des erreurs de type au moment de la compilation.

Vous pouvez facilement créer les objets requis en copiant votre JSON en mémoire et en le collant sous forme d'objets JSON (Visual Studio -> Edit -> Paste Special -> Paste JSON as Classes).

Ver aquí si vous n'avez pas cette option dans Visual Studio.

Vous devrez également vous assurer que votre JSON est valide. Ajoutez votre propre objet au début s'il s'agit simplement d'un tableau d'objets, c'est-à-dire { "obj" : [{},{},{}]}

** Je sais que dynamique rend les choses plus faciles parfois, mais je suis un peu vieux jeu avec ça.

1 votes

C'est l'approche de la programmation que je préfère. J'aime les objets fortement typés. Merci, car j'ai utilisé et modifié ce code.

0 votes

Cette fonctionnalité de collage en JSON est géniale ! J'ai gagné beaucoup de temps

22voto

Rick Leitch Points 141

Corrigez-moi si je me trompe, mais l'exemple précédent est, je crois, légèrement décalé par rapport à la dernière version de la bibliothèque Json.NET de James Newton.

var o = JObject.Parse(stringFullOfJson);
var page = (int)o["page"];
var totalPages = (int)o["total_pages"];

1 votes

Merci pour votre réponse Rick, oui cela ressemble aux exemples que j'ai trouvé dans la documentation la plus récente aussi.

1 votes

Oui, depuis qu'Arcain a corrigé la faute de frappe, mon commentaire a l'air d'être une erreur :'(. J'ai posté à l'origine parce que je ne reconnaissais pas JToken.Parse.

1 votes

Je ne suis pas du tout pointilleux - il y a vraiment était une erreur, et il y a toujours plus d'une façon de le faire. A propos, ma version de Json.NET supporte la syntaxe utilisant l'indexeur sur JObject mais le code que j'ai modifié pour ma réponse a été tiré d'un code utilisant une surcharge de la fonction SelectToken afin de pouvoir supprimer les exceptions si le jeton n'était pas trouvé : JToken JToken.SelectToken(string tokenName, bool errorWhenNoMatch) C'est donc de là que vient la verbosité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X