Удаление десериализации JSON в .NET-объект с использованием Newtonsoft (или LINQ to JSON, возможно?)
Я знаю, что есть несколько сообщений о Newtonsoft, так что, надеюсь, это не совсем повторение... Я пытаюсь преобразовать данные JSON, возвращенные Kazaa API, в хороший объект какого-то рода
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 - это всего лишь последняя, которую я пытался... Я не совсем понял ее и надеялся устранить некоторые проблемы, спросив вас, ребята. Сначала я пытался преобразовать его в словарь или что-то в этом роде... и на самом деле мне просто нужно заглушить пару значений, поэтому, судя по документации, возможно, Newtonsoft LINQ to 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": "\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
}
Я еще немного читал и нашел, что Newtonsoft LINQ to 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"]);
}
Ответы
Ответ 1
Если вам просто нужно получить несколько элементов из объекта JSON, я бы использовал класс Json.NET 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
Ответ 2
Вы можете использовать dynamic
тип С#, чтобы упростить задачу. Этот метод также упрощает повторный факторинг, поскольку он не полагается на магические струны.
JSON
Строка JSON ниже - это простой ответ от вызова HTTP API, и он определяет два свойства: Id
и Name
.
{"Id": 1, "Name": "biofractal"}
С#
Используйте 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.
Ответ 3
С ключевым словом 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;
}
Ответ 4
Исправьте меня, если я ошибаюсь, но предыдущий пример, я считаю, немного не синхронизирован с последней версией библиотеки Джеймса Ньютона Json.NET.
var o = JObject.Parse(stringFullOfJson);
var page = (int)o["page"];
var totalPages = (int)o["total_pages"];
Ответ 5
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;
}
Ответ 6
Кроме того, если вы просто ищете определенное значение, вложенное в содержимое JSON, вы можете сделать что-то вроде этого:
yourJObject.GetValue("jsonObjectName").Value<string>("jsonPropertyName");
И так далее оттуда.
Это может помочь, если вы не хотите нести стоимость преобразования всего JSON в объект С#.
Ответ 7
Если, как и я, вы предпочитаете иметь дело с сильно типизированными объектами ** идите с:
MyObj obj = JsonConvert.DeserializeObject<MyObj>(jsonString);
Таким образом вы можете использовать проверку ошибок типа intellisense и компиляции.
Вы можете легко создать необходимые объекты, скопировав JSON в память и вставив его в качестве объектов JSON (Visual Studio → Edit → Paste Special → Paste JSON as Classes).
Смотрите здесь, если у вас нет этой опции в Visual Studio.
Вам также необходимо убедиться, что ваш JSON действителен. Добавьте свой собственный объект в начале, если это всего лишь массив объектов. то есть { "obj": [{}, {}, {}]}
** Я знаю, что динамический делает вещи проще, но я немного олсул с этим.
Ответ 8
Мне нравится этот метод:
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.
Ответ 9
Наконец, получите имя штата от 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
Ответ 10
Я преклонил 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);
Ответ 11
Я очень поздно опоздал на эту вечеринку, но сегодня я столкнулся с этим вопросом на работе. Вот как я решил проблему.
Я получал доступ к стороннему API для получения списка книг. Объект возвратил массивный объект JSON, содержащий примерно 20+ поля, из которых мне нужен только идентификатор как объект строки List. Я использовал linq для динамического объекта, чтобы получить нужное поле, а затем ввел его в свой объект строки List.
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());
}