Удаление десериализации JSON в .NET-объект с использованием Newtonsoft (или LINQ to JSON, возможно?)

Я знаю, что есть несколько сообщений о Newtonsoft, поэтому, надеюсь, это не совсем повторение … Я пытаюсь преобразовать данные JSON, возвращенные API Kazaa, в хороший объект какого-то типа

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

Эта линия JsonConvert – это всего лишь последняя, ​​которую я пытался … Я не совсем понял ее и надеялся устранить некоторые проблемы, спросив вас, ребята. Первоначально я пытался преобразовать его в словарь или что-то еще … и на самом деле мне просто нужно зацепить пару значений, так что, судя по документации, возможно, лучше использовать LINQ to JSON от Newtonsoft? Мысли / ссылки?

Вот пример возвращаемых данных 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 } 

Я прочитал еще немного и нашел, что LINQ для LINKS для JSON – это именно то, что я хотел … используя WebClient, Stream, StreamReader и Newtonsoft … Я могу ударить Kazaa для данных JSON, извлечь URL-адрес, загрузить файл и сделать это все в виде семи строк кода! Я люблю это.

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

Это сообщение получает так много хитов, я думал, что было бы полезно включить «использование» битов, которые обсуждаются в комментариях.

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

Если вам просто нужно получить несколько элементов из объекта JSON, я бы использовал class LINQ JSON для JSON JObject . Например:

 JToken token = JObject.Parse(stringFullOfJson); int page = (int)token.SelectToken("page"); int totalPages = (int)token.SelectToken("total_pages"); 

Мне нравится этот подход, потому что вам не нужно полностью десериализовать объект JSON. Это пригодится API-интерфейсам, которые иногда могут удивить вас отсутствием свойств объекта, например Twitter.

Документация: Сериализация и десериализация JSON с Json.NET и LINQ to JSON с Json.NET

Вы можете использовать dynamic тип C #, чтобы упростить задачу. Этот метод также упрощает повторный факторинг, поскольку он не полагается на магические струны.

JSON

Строка JSON ниже – это простой ответ от вызова HTTP API, и он определяет два свойства: Id и Name .

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

C #

Используйте JsonConvert.DeserializeObject() чтобы десериализовать эту строку в динамический тип, а затем просто получить доступ к ее свойствам обычным способом.

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

Если вы укажете тип переменной results как dynamic , вместо использования ключевого слова var , значения свойств будут корректно десериализоваться, например Id для int а не JValue (спасибо GFoley83 за комментарий ниже).

Примечание . Ссылка NuGet для сборки Newtonsoft – http://nuget.org/packages/newtonsoft.json .

С ключевым словом dynamic становится очень легко разобрать любой объект такого типа:

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

Исправьте меня, если я ошибаюсь, но, как мне кажется, предыдущий пример немного не синхронизирован с последней версией библиотеки Json.NET Джеймса Ньютона.

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

Deserialize и получить значение (когда коллекция динамична):

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

Кроме того, если вы просто ищете определенное значение, nested в содержимое JSON, вы можете сделать что-то вроде этого:

 yourJObject.GetValue("jsonObjectName").Value("jsonPropertyName"); 

И так далее оттуда.

Это может помочь, если вы не хотите нести стоимость преобразования всего JSON в объект C #.

Если, как и я, вы предпочитаете иметь дело с сильно типизированными объектами ** идите с:

 MyObj obj = JsonConvert.DeserializeObject(jsonString); 

Таким образом вы можете использовать проверку ошибок типа intellisense и компиляции.

Вы можете легко создать необходимые объекты, скопировав JSON в память и вставив его в качестве объектов JSON (Visual Studio -> Edit -> Paste Special -> Paste JSON as Classes).

См. Здесь, если у вас нет этой опции в Visual Studio.

Вам также необходимо убедиться, что ваш JSON действителен. Добавьте свой собственный объект в начале, если это всего лишь массив объектов. т.е. { “obj”: [{}, {}, {}]}

** Я знаю, что динамика облегчает ситуацию, но я немного олскул с этим.

Мне нравится этот метод:

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

Теперь вы можете получить доступ к чему угодно, используя dictObj в качестве словаря. Вы также можете использовать Dictionary если вы предпочитаете получать значения в виде строк.

Вы можете использовать этот же метод для применения в качестве любого объекта .NET.

Наконец, получите имя штата от JSON

Спасибо!

 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 

Я преклонил Extionclass для 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); } } 

Дизайн-шаблон:

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

Применение:

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

Я очень поздно опоздал на эту вечеринку, но сегодня я столкнулся с этим вопросом на работе. Вот как я решил проблему.

Я получал доступ к стороннему API для получения списка книг. Объект возвратил массивный объект JSON, содержащий примерно 20+ полей, из которых мне нужен только идентификатор как объект строки List. Я использовал linq для динамического объекта, чтобы получить нужное поле, а затем ввел его в свой объект строки List.

 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()); } 
  • JSON для экземпляра classа TypeScript?
  • Полиморфизм в аннотациях jacksonа: использование @JsonTypeInfo
  • Можно ли указать путь в атрибуте для сопоставления свойства в моем classе с дочерним свойством в моем JSON?
  • Json.NET Отключить десериализацию в DateTime
  • Разбор большого json-файла в .NET.
  • Сериализация - readObject writeObject переопределяет
  • Дессериализация данных JSON на C # с использованием JSON.NET
  • Библиотека Jackson JSON: как создать экземпляр classа, содержащего абстрактные поля
  • Как реализовать пользовательский JsonConverter в JSON.NET для десериализации списка объектов базового classа?
  • Как я могу разбирать JSON с C #?
  • Давайте будем гением компьютера.