web-dev-qa-db-fra.com

Désérialisation des objets JSON en objets .NET avec Newtonsoft (ou LINQ to JSON peut-être?)

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

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 n’est que la plus récente que j’ai essayée ... Je ne l’ai pas très bien comprise et j’espérais éliminer le jeu de jambes en vous le demandant. Au départ, j'essayais de le convertir en dictionnaire ou quelque chose du genre ... et en fait, je dois simplement y attacher quelques valeurs, alors à en juger par la documentation, peut-être que LINQ to JSON de Newtonsoft pourrait être un meilleur choix? Pensées/Liens?

Voici un exemple des 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 trouvé que LINQ to JSON de Newtonsoft était exactement ce que je voulais ... utiliser WebClient, Stream, StreamReader et Newtonsoft ... Je peux utiliser Kazaa pour obtenir des données JSON, extraire une URL, télécharger le fichier et le faire tout en sept lignes de code! J'aime cela.

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

Ce billet reçoit tellement de résultats que j'ai pensé qu'il pourrait être utile d'inclure les bits "d'utilisation" décrits 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"]);
}
291
J Benjamin

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

JToken token = JObject.Parse(stringFullOfJson);

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

J'aime cette approche car il n'est pas nécessaire de désérialiser complètement l'objet JSON. Cela est 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 et LINQ to JSON avec Json.NET

241
arcain

Vous pouvez utiliser le type C # dynamic pour faciliter les choses. Cette technique simplifie également la reconfiguration car elle ne repose pas sur des chaînes magiques.

JSON

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

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

C #

Utilisez JsonConvert.DeserializeObject<dynamic>() pour désérialiser cette chaîne en un type dynamique, puis accédez 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 variable results sous la forme dynamic, au lieu d'utiliser le mot clé var, les valeurs de propriété seront alors correctement désérialisées, par exemple Id à int et non JValue (merci à GFoley83 pour le commentaire ci-dessous).

Note: Le lien NuGet de Newtonsoft Assembly est http://nuget.org/packages/newtonsoft.json .

248
biofractal

Avec le mot clé 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;
}
33
Sushant Srivastava

Corrigez-moi si je me trompe, mais l'exemple précédent, je crois, est légèrement désynchronisé 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"];
21
Rick Leitch

Désérialiser et obtenir la valeur (lorsque la collection est dynamique):

// First serializing
dynamic collection = new { stud = stud_datatable }; // The stud_datable is the list or data table
string jsonString = JsonConvert.SerializeObject(collection);


// Second Deserializing
dynamic StudList = JsonConvert.DeserializeObject(jsonString);

var stud = StudList.stud;
foreach (var detail in stud)
{
    var Address = detail["stud_address"]; // Access Address data;
}
10
Arun Prasad E S

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

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

De cette façon, vous utilisez intellisense et compilez la vérification des erreurs de type de temps.

Vous pouvez facilement créer les objets requis en copiant votre JSON dans la mémoire et en le collant en tant qu'objets JSON (Visual Studio -> Édition -> Collage spécial -> Coller JSON en tant que classes).

Voir ici 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 ne s'agit que d'un tableau d'objets. c'est-à-dire {"obj": [{}, {}, {}]}

** Je sais que dynamic facilite parfois les choses, mais je suis un peu fou avec ça.

8
Guy Lowe

En outre, si vous recherchez simplement une valeur spécifique imbriquée dans le contenu JSON, vous pouvez procéder de la manière suivante:

yourJObject.GetValue("jsonObjectName").Value<string>("jsonPropertyName");

Et ainsi de suite.

Cela pourrait vous aider si vous ne voulez pas supporter le coût de la conversion de l'ensemble du code JSON en objet C #.

7
Tony Anderson

J'aime cette méthode:

using Newtonsoft.Json.Linq;
// jsonString is your JSON-formatted string
JObject jsonObj = JObject.Parse(jsonString);
Dictionary<string, object> dictObj = jsonObj.ToObject<Dictionary<string, object>>();

Vous pouvez maintenant accéder à tout ce que vous voulez en utilisant dictObj comme dictionnaire. Vous pouvez également utiliser Dictionary<string, string> si vous préférez obtenir les valeurs sous forme de chaînes.

Vous pouvez utiliser cette même méthode pour attribuer n'importe quel type d'objet .NET.

6
Blairg23

j'ai créé une classe d'action pour JSON:

 public static class JsonExtentions
    {
        public static string SerializeToJson(this object SourceObject) { return Newtonsoft.Json.JsonConvert.SerializeObject(SourceObject); }


        public static T JsonToObject<T>(this string JsonString) { return (T)Newtonsoft.Json.JsonConvert.DeserializeObject<T>(JsonString); }
}

Design pattern:

 public class Myobject
    {
        public Myobject(){}
        public string prop1 { get; set; }

        public static Myobject  GetObject(string JsonString){return  JsonExtentions.JsonToObject<Myobject>(JsonString);}
        public  string ToJson(string JsonString){return JsonExtentions.SerializeToJson(this);}
    }

Usage:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);
1
Sloomy

Assez tard pour cette soirée, mais je suis tombé sur ce problème moi-même aujourd'hui au travail. Voici comment j'ai résolu le problème.

J'avais accès à une API tierce pour récupérer une liste de livres. L'objet a renvoyé un objet JSON massif contenant environ 20 champs et plus, dont je n'avais besoin que de l'ID en tant qu'objet chaîne List. J'ai utilisé linq sur l'objet dynamique pour récupérer le champ spécifique dont j'avais besoin, puis je l'ai inséré dans mon objet de chaîne List.

dynamic content = JsonConvert.DeserializeObject(requestContent);
var contentCodes = ((IEnumerable<dynamic>)content).Where(p => p._id != null).Select(p=>p._id).ToList();

List<string> codes = new List<string>();

foreach (var code in contentCodes)
{
    codes.Add(code?.ToString());
}
1
todd.pund

Enfin, obtenez le nom d'état de JSON

Je vous remercie!

Imports System
Imports System.Text
Imports System.IO
Imports System.Net
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.collections.generic

Public Module Module1
    Public Sub Main()

         Dim url As String = "http://maps.google.com/maps/api/geocode/json&address=attur+salem&sensor=false"
            Dim request As WebRequest = WebRequest.Create(url)
        dim response As WebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        dim reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
          Dim dataString As String = reader.ReadToEnd()

        Dim getResponse As JObject = JObject.Parse(dataString)

        Dim dictObj As Dictionary(Of String, Object) = getResponse.ToObject(Of Dictionary(Of String, Object))()
        'Get State Name
        Console.WriteLine(CStr(dictObj("results")(0)("address_components")(2)("long_name")))
    End Sub
End Module
0
iApps Creator