2011-01-20 49 views
252

Sé que hay algunas publicaciones sobre Newtonsoft, así que espero que esto no sea exactamente una repetición ... Estoy intentando convertir datos JSON devueltos por API de Kazaa en un bonito objeto de algún tipoDeserialización de objeto JSON a .NET usando Newtonsoft (¿o LINQ a JSON quizás?)

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

Esa línea JsonConvert es sólo el más reciente que estaba tratando ... no estoy bastante conseguirlo y esperaba para eliminar una serie de paredes pidiendo a ustedes. Originalmente estaba tratando de convertirlo en un diccionario o algo así ... y en realidad, solo necesito obtener un par de valores allí, así que a juzgar por la documentación, ¿quizás LINQ to JSON de Newtonsoft podría ser una mejor opción? Pensamientos/Enlaces

Aquí es un ejemplo de los datos JSON retorno:

{ 
    "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 
} 

he hecho un poco más lectura y encontré LINQ de Newtonsoft a JSON es exactamente lo que quería ... utilizando WebClient, Stream, StreamReader, y Newtonsoft ... ¡puedo presionar Kazaa para obtener datos JSON, extraer una URL, descargar el archivo y hacerlo todo como siete líneas de código! Lo amo.

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

Este post se pone golpes hasta que pensé que podría ser útil para incluir los bits de "usar" que se discuten en los comentarios.

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

Ejemplo elegante, gracias. Solo una sugerencia: puede haber dejado esto para abreviar, pero dado que 'WebClient',' Stream' y 'StreamReader' implementan 'IDisposable', es posible que desee agregar algunos bloques' using' a su código. – arcain

+0

ah sí, buena idea ... (esta era en realidad solo una aplicación de consola que estaba corriendo muy rápido para investigar las tareas que venía) Ahora fuera a investigar la última pieza del enigma, cifrado HLS + AES :) ugh ...lol –

+1

+1 Gracias por publicar el ejemplo de Linq. Exactamente lo que necesitaba. –

Respuesta

213

Si sólo tiene que conseguir algunos artículos de objeto JSON, me gustaría utilizar LINQ de Json.NET a JSON JObject clase. Por ejemplo:

JToken token = JObject.Parse(stringFullOfJson); 

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

Me gusta este enfoque porque no necesita deserializar completamente el objeto JSON. Esto es útil con las API que a veces pueden sorprenderte con las propiedades de objetos faltantes, como Twitter.

Documentación: Serializing and Deserializing JSON with Json.NET y LINQ to JSON with Json.NET

+1

ya he hecho un poco más de lectura y prueba ... encontré que esta es una buena manera de hacerlo también ... Newtonsoft, una biblioteca muy bonita, publicaré mi ejemplo para otros –

+1

publicado un ejemplo aproximado de cómo lo estaba haciendo ... no exactamente lo mismo, veo que sugeriste a JToken.Parse ... no estoy seguro de las diferencias entre los dos pero, ¡ya, buenas cosas! –

+0

@Jbenjamin Gracias! Eso fue un error tipográfico JToken es la clase base para JObject, y es solo mi preferencia personal trabajar con el tipo más abstracto. Gracias por llamar eso a mi atención. – arcain

20

Corrígeme si me equivoco, pero el ejemplo anterior, creo, es sólo un poco fuera de sincronización con la última versión de la biblioteca Json.NET de James Newton.

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

gracias por su respuesta Rick, ya que se parece a los ejemplos que encontré en la documentación más reciente también. –

+1

Sí, desde que Arcain arregló el error tipográfico, mi comentario ahora se ve insignificante: '(. Originalmente publiqué porque no reconocí a JToken.Parse. –

+1

No es para nada quisquilloso - definitivamente * fue * un error, y siempre hay más que una forma de hacerlo. Por cierto, mi versión de Json.NET soporta la sintaxis usando el indexador en 'JObject', pero el código que modifiqué para mi respuesta fue extraído del código haciendo uso de una sobrecarga del' SelectToken 'método para poder suprimir excepciones si no se encontró el token:' JToken JToken.SelectToken (string tokenName, bool errorWhenNoMatch) ', así que de ahí viene la verbosidad. – arcain

219

Puede usar el tipo C# dynamic para facilitar las cosas. Esta técnica también simplifica el refaccionamiento, ya que no depende de cadenas mágicas.

JSON

La cadena JSON a continuación es una respuesta sencilla a partir de una llamada API HTTP, y define dos propiedades: Id y Name.

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

C#

Uso JsonConvert.DeserializeObject<dynamic>() deserializar esta cadena en un tipo dinámico entonces simplemente acceder a sus propiedades de la forma habitual.

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

Si especifica el tipo de la variable results como dynamic, en lugar de utilizar la palabra clave var, a continuación, los valores de las propiedades correctamente se deserializar, por ejemplo, Id a int y no a JValue (gracias a GFoley83 para el comentario a continuación).

Nota: El enlace NuGet para el montaje Newtonsoft es http://nuget.org/packages/newtonsoft.json.

+10

+1 Usar 'dynamic' es el camino a seguir aquí IMO. –

+0

Estaba usando el mismo fragmento de código que el anterior para deserializar la respuesta de twitter con newtonsoft.dll versión 4.5.6 y funcionaba bien ... pero después de actualizarlo a la versión 5.0.6 .. comenzó a lanzar error ... ¿Alguna idea de por qué? – Pranav

+0

Bueno para objetos dinámicos, cuando sabemos o tenemos clase C# por lo que podemos consumir como una clase C# en reemplazo de dinámica, p. . – MSTdev

31

Con la palabra clave dynamic, se hace muy fácil de analizar cualquier objeto de este 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

Quería saber cómo recorrer los resultados y esto llevó demasiado tiempo encontrar ... ¡¡¡Gracias !! – batoutofhell

7

Además, si usted está en busca de un valor específico anidado dentro del contenido JSON se puede hacer algo como entonces:

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

Y así sucesivamente desde allí.

Esto podría ayudar si no quiere asumir el costo de convertir el JSON completo en un objeto C#.

10

Deserialize y obtener el valor (cuando la colección es dinámica):

// 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

Me gusta este método:

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

Ahora puede acceder a cualquier cosa que desee mediante el dictObj como un diccionario. También puede usar Dictionary<string, string> si prefiere obtener los valores como cadenas.

Puede utilizar este mismo método para convertirlo en cualquier tipo de objeto .NET.

+1

Me parece muy agradable este método por dos razones: 1) cuando no te importa el tipo de datos (todo es cadena), y 2) es conveniente trabajar con un diccionario de los valores – netfed

4

Si, como yo, prefiere tratar con objetos inflexible ** ir con:

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

De esta manera se llega a utilizar IntelliSense y compilar la comprobación de tipos de error de tiempo.

Puede crear fácilmente los objetos requeridos copiando su JSON en la memoria y pegándolo como objetos JSON (Visual Studio -> Editar -> Pegar especial -> Pegar JSON como clases).

Consulte here si no tiene esa opción en Visual Studio.

También deberá asegurarse de que su JSON sea válido. Agregue su propio objeto al principio si solo se trata de una matriz de objetos. es decir, {"obj": [{}, {}, {}]}

** Sé que dinámica facilita las cosas a veces, pero estoy un poco ol'skool con esto.

Cuestiones relacionadas