Десериализация JSON в .NET объект с использованием Newtonsoft (или LINQ to JSON, может быть?) - PullRequest
297 голосов
/ 20 января 2011

Я знаю, что есть несколько сообщений о 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<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();

Эта линия JsonConvert является самой последней из тех, что я пробовал ... Я не совсем понял, и надеялся избавиться от лишней работы, спрашивая вас, ребята.Первоначально я пытался преобразовать его в словарь или что-то в этом роде ... и на самом деле мне просто нужно поймать там несколько значений, поэтому, судя по документации, может быть, LINTON 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",
      "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
}

Я прочитал еще несколько слов и обнаружил, что LINQ to JSON от Newtonsoft именно то, что я хотел ...using 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", которые обсуждаются в комментариях.

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

Ответы [ 11 ]

258 голосов
/ 23 мая 2012

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

JSON

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

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

C #

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

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

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

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

Пакет : Вы также можете добавить пакет с помощью установщика Nuget Live, когда ваш проект открыт, просто выполните , просмотрите пакет , а затем просто установите его установить,unistall, обновите , он будет просто добавлен в ваш проект под Dependencies / NuGet

245 голосов
/ 20 января 2011

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

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

36 голосов
/ 28 августа 2014

С ключевым словом 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;
}
21 голосов
/ 20 января 2011

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

var o = JObject.Parse(stringFullOfJson);
var page = (int)o["page"];
var totalPages = (int)o["total_pages"];
13 голосов
/ 14 июля 2017

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

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

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

Вы можете легко создать необходимые объекты, скопировав JSON в память и вставив его в виде объектов JSON (Visual Studio -> Правка -> Специальная вставка -> Вставить JSON как классы).

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

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

** Я знаю, что dynamic иногда делает вещи проще, но янемного ольскоул с этим.

10 голосов
/ 04 ноября 2015

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

// 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;
}
8 голосов
/ 29 марта 2016

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

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

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

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

7 голосов
/ 15 января 2015

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

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

И так далее.

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

2 голосов
/ 08 июня 2018

я создал Extionclass для 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); }
}

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

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

Использование:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);
1 голос
/ 13 июля 2018

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

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

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