2011-01-20 13 views
252

So che ci sono alcuni post su Newtonsoft quindi spero che non sia esattamente una ripetizione ... Sto provando a convertire i dati JSON restituiti da API di Kazaa in un bel oggetto di qualche tipoDeserializzazione dell'oggetto JSON in .NET usando Newtonsoft (o LINQ to JSON forse?)

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

quella linea JsonConvert è solo il più recente stavo cercando ... non sto abbastanza ottenerlo e speravo di eliminare alcuni footwork chiedendo voi ragazzi. Inizialmente cercavo di convertirlo in un dizionario o qualcosa del genere ... e in realtà, ho solo bisogno di impadronirci di un paio di valori così a giudicare dalla documentazione, forse LINQ di Newtonsoft per JSON potrebbe essere una scelta migliore? Pensieri/link?

Ecco un esempio dei dati di ritorno 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 
} 

ho fatto un po 'di lettura e trovato LINQ di Newtonsoft per JSON è esattamente quello che volevo ... usando WebClient, Stream, StreamReader, e Newtonsoft ... Posso colpire Kazaa per i dati JSON, estrarre un URL, scaricare il file e fare tutto in sette righe di codice uguali! Lo adoro.

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

Questo post ottiene così tanti successi che ho pensato che potrebbe essere utile per includere i bit "usando" che vengono discussi nei commenti.

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"]); 
} 
+6

Slick esempio, grazie. Solo un suggerimento: potresti averlo lasciato per brevità, ma dal momento che 'WebClient',' Stream' e 'StreamReader' implementano' IDisposable', potresti voler aggiungere alcuni blocchi 'using' al tuo codice. – arcain

+0

ah sì, buona chiamata ... (si trattava in realtà solo di un'app per console che stavo correndo molto velocemente per cercare i compiti che mi venivano proposti) Ora via per cercare l'ultimo pezzo del puzzle, crittografia HLS + AES :) ugh ...lol –

+1

+1 Grazie per aver postato l'esempio di Linq. Esattamente quello di cui avevo bisogno. –

risposta

213

Se avete solo bisogno di ottenere alcuni elementi dalla oggetto JSON, vorrei utilizzare LINQ di Json.NET a JSON JObject classe. Ad esempio:

Mi piace questo approccio perché non è necessario deserializzare completamente l'oggetto JSON. Questo è utile con le API che a volte possono sorprenderti con le proprietà degli oggetti mancanti, come Twitter.

Documentazione: Serializing and Deserializing JSON with Json.NET e LINQ to JSON with Json.NET

+1

ya Ho effettivamente fatto un po 'più di lettura e test ... ho trovato che questo è un buon modo per farlo ... Newtonsoft, una bella libreria, posterò il mio esempio per gli altri –

+1

pubblicato un esempio approssimativo di come lo stavo facendo ... non proprio la stessa cosa, vedo che hai suggerito JToken.Parse ... non sono sicuro delle differenze tra i due ma, ah, roba buona! –

+0

@Jbenjamin Grazie! Quello era un errore di battitura. JToken è la classe base per JObject, ed è solo una mia preferenza personale lavorare con il tipo più astratto. Grazie per averlo chiamato alla mia attenzione. – arcain

20

mi corregga se sbaglio, ma l'esempio precedente, credo, è solo leggermente fuori sincronia con l'ultima versione della libreria Json.NET di James Newton.

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

grazie per la tua risposta Rick, ti ​​sembra simile agli esempi che ho trovato anche nella documentazione più recente. –

+1

Sì, dal momento che arcain ha corretto l'errore di battitura, il mio commento ora sembra nitpicky: '(. Originariamente pubblicato perché non riconoscevo JToken.Parse. –

+1

Niente affatto per niente - sicuramente * era * un errore, e c'è sempre di più A proposito, la mia versione di Json.NET supporta la sintassi usando l'indicizzatore su 'JObject', ma il codice che ho modificato per la mia risposta è stato estratto dal codice facendo uso di un overload del' SelectToken 'metodo in modo da poter sopprimere le eccezioni se il token non è stato trovato:' JToken JToken.SelectToken (string tokenName, bool errorWhenNoMatch) ', ecco da dove viene la verbosità. – arcain

219

È possibile utilizzare il tipo C# dynamic per semplificare le cose. Questa tecnica rende anche il ri-factoring più semplice in quanto non si basa su stringhe magiche.

JSON

La stringa JSON segue è una risposta semplice da una chiamata API HTTP, e definisce due proprietà: Id e Name.

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

C#

Usa JsonConvert.DeserializeObject<dynamic>() deserializzare questa stringa in un tipo dinamico quindi è sufficiente accedere alla sua proprietà nel solito modo.

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

Se si specifica il tipo di variabile results come dynamic, invece di utilizzare la parola chiave var, quindi i valori delle proprietà saranno correttamente deserializzare, per esempio Id a int e non a JValue (grazie a GFoley83 per il commento seguente).

Nota: il collegamento NuGet per l'assembly Newtonsoft è http://nuget.org/packages/newtonsoft.json.

+10

+1 Usare 'dynamic' è la strada da percorrere qui IMO. –

+0

Stavo usando lo stesso pezzo di codice di cui sopra per deserializzare la risposta di twitter con newtonsoft.dll versione 4.5.6 e funzionava bene ..ma dopo l'aggiornamento alla versione 5.0.6 .. ha iniziato a lanciare l'errore .. Qualche idea del perché ?? – Pranav

+0

Buono per oggetti dinamici, quando sappiamo o abbiamo classe C# in modo che possiamo consumare come classe C# in sostituzione di dynamic, ad es. . – MSTdev

31

Con la parola chiave dynamic, diventa davvero facile da analizzare qualsiasi oggetto di questo tipo:

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

Volevo sapere come scorrere i risultati e questo ha richiesto troppo tempo per trovare ... grazie !! – batoutofhell

7

Inoltre, se siete solo in cerca di un valore specifico annidato all'interno del contenuto JSON si può fare qualcosa di simile quindi:

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

E così via da lì.

Questo potrebbe aiutare se non si vuole sostenere il costo di convertire l'intero JSON in un oggetto C#.

10

Deserialize e ottenere il valore (quando la raccolta è dinamico):

// 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; 
} 
4

Mi piace questo metodo:

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

È ora possibile accedere a qualsiasi cosa che si desidera utilizzare il dictObj come un dizionario. Puoi anche usare Dictionary<string, string> se preferisci ottenere i valori come stringhe.

È possibile utilizzare questo stesso metodo per eseguire il cast di qualsiasi tipo di oggetto .NET.

+1

Trovo questo metodo molto carino per due motivi: 1) quando non ti interessa il tipo di dati (tutto è una stringa) e 2) è conveniente lavorare con un dizionario dei valori – netfed

4

Se, come me, si preferisce trattare con oggetti fortemente tipizzati ** andare con:

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

In questo modo si arriva a usare intellisense e compilare il tempo controllo tipo di errore.

È possibile creare facilmente gli oggetti richiesti copiando il JSON in memoria e incollandolo come oggetti JSON (Visual Studio -> Modifica -> Incolla speciale -> Incolla JSON come classi).

Vedere here se non si dispone di tale opzione in Visual Studio.

Sarà inoltre necessario assicurarsi che il proprio JSON sia valido. Aggiungi il tuo oggetto all'inizio se è solo un array di oggetti. vale a dire {"obj": [{}, {}, {}]}

** So che dinamica rende le cose più facili, ma a volte sono un po 'ol'skool con questo.

Problemi correlati