Десериализация JSON to.NET объект, использующий Newtonsoft(или LINQ для 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<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-самая последняя, которую я пробовал...Я не совсем понимаю и надеялся устранить некоторую работу ног, спросив вас, ребята. Первоначально я пытался преобразовать его в словарь или что-то в этом роде...и на самом деле, мне просто нужно добавить пару значений в там, судя по документации, может быть, LINQ Newtonsoft для JSON может быть лучшим выбором? Мысли / Ссылки?

вот пример данных возврата 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": "u76e7u5de7u97f3"
    },
    {
      "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 Newtonsoft для 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"]);
}

11 ответов


Если вам просто нужно получить несколько элементов из объекта JSON, я бы использовал Json.NET ' S LINQ to 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


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

JSON

строка JSON ниже-это простой ответ от вызова HTTP API, и он определяет два свойства: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 переменная as 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"];

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

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

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

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

и так далее.

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


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

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

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

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

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

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

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


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

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.


наконец получить имя состояния из 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<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);

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

Я обращался к стороннему API, чтобы получить список книг. Объект вернул массивный объект JSON, содержащий примерно 20 + полей, из которых мне нужен был только ID как объект строки списка. Я использовал 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());
}