¿Deserializar el objeto JSON a .NET usando Newtonsoft (o LINQ a JSON quizás?)

Sé que hay algunas publicaciones sobre Newtonsoft, así que espero que esto no sea exactamente una repetición … Estoy tratando de convertir los datos JSON devueltos por la API de Kazaa en un objeto agradable de algún tipo.

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 list = Newtonsoft.Json.JsonConvert.DeserializeObject<List>(reader.Read().ToString()); foreach (string item in list) { Console.WriteLine(item); } //Console.WriteLine(reader.ReadLine()); stream.Close(); 

Esa línea JsonConvert es la más reciente que estaba intentando … No la estoy entendiendo del todo y esperaba eliminar el trabajo de pies preguntándoles chicos. 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í hay un ejemplo de los datos de retorno 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", "id": 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 } 

Hice algunas lecturas más y encontré que el LINQ de Newtonsoft a JSON es exactamente lo que quería … usar WebClient, Stream, StreamReader y Newtonsoft … Puedo presionar Kazaa para obtener datos JSON, extraer una URL, descargar el archivo y hacerlo todo en 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(); 

Esta publicación recibe tantos éxitos que pensé que podría ser útil incluir los bits de “uso” que se comentan 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"]); } 

Si solo necesitas obtener algunos elementos del objeto JSON, usaría el LINQ de JObject clase JSON JObject . 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 por completo el objeto JSON. Esto es útil con las API que a veces pueden sorprenderte con las propiedades de objetos faltantes, como Twitter.

Documentación: serializar y deserializar JSON con Json.NET y LINQ a JSON con Json.NET

Puede usar el tipo dynamic C # 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 simple de una llamada API HTTP, y define dos propiedades: Id y Name .

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

DO#

Utilice JsonConvert.DeserializeObject() para deserializar esta cadena en un tipo dynamic y luego simplemente acceda a sus propiedades de la forma habitual.

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

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

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

Con la palabra clave dynamic , se vuelve realmente fácil 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; } 

Corrígeme si me equivoco, pero el ejemplo anterior, creo, está ligeramente 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"]; 

Deserializar 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; } 

Además, si solo está buscando un valor específico nested dentro del contenido JSON, puede hacer algo como esto:

 yourJObject.GetValue("jsonObjectName").Value("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 #.

Si, como yo, prefieres tratar con objetos muy tipados ** ve con:

 MyObj obj = JsonConvert.DeserializeObject(jsonString); 

De esta forma, puede utilizar intellisense y comstackr la comprobación de errores del tipo 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 aquí 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. ie { “obj”: [{}, {}, {}]}

** Sé que la dinámica hace las cosas más fáciles a veces, pero estoy un poco viejo con esto.

Me gusta este método:

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

Ahora puede acceder a cualquier cosa que desee utilizando el dictObj como diccionario. También puede usar Dictionary si prefiere obtener los valores como cadenas.

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

Finalmente, obtenga el nombre de estado de JSON

¡Gracias!

 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 

Arreglé una Extionclass para json:

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

Patrón de diseño:

  public class Myobject { public Myobject(){} public string prop1 { get; set; } public static Myobject GetObject(string JsonString){return JsonExtentions.JsonToObject(JsonString);} public string ToJson(string JsonString){return JsonExtentions.SerializeToJson(this);} } 

Uso:

  Myobject dd= Myobject.GetObject(jsonstring); Console.WriteLine(dd.prop1); 

Ya es tarde para esta fiesta, pero hoy me encontré con este problema en el trabajo. Aquí es cómo resolví el problema.

Estaba accediendo a una API de terceros para recuperar una lista de libros. El objeto devolvió un objeto JSON masivo que contiene aproximadamente más de 20 campos, de los cuales solo necesitaba el ID como un objeto de cadena de lista. Usé linq en el objeto dynamic para recuperar el campo específico que necesitaba y luego lo inserté en mi objeto de cadena de lista.

 dynamic content = JsonConvert.DeserializeObject(requestContent); var contentCodes = ((IEnumerable)content).Where(p => p._id != null).Select(p=>p._id).ToList(); List codes = new List(); foreach (var code in contentCodes) { codes.Add(code?.ToString()); }