Десериализация 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переменная asdynamic, вместо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#.
если, как и я, вы предпочитаете иметь дело со строго типизированными объектами * * идите с:
MyObj obj = JsonConvert.DeserializeObject<MyObj>(jsonString);таким образом, вы можете использовать intellisense и проверку ошибок типа времени компиляции.
вы можете легко создать необходимые объекты, скопировав JSON в память и вставив его как объекты JSON (Visual Studio -> Edit -> Paste Special -> Paste JSON as Classes).
посмотреть здесь если у вас нет этой опции в Visual Studio.
будут необходимо убедиться, что ваш JSON действителен. Добавьте свой собственный объект в начале, если это просто массив объектов. то есть { "obj":[{},{},{}]}
** Я знаю, что динамический делает вещи проще иногда, но я немного ol'Skool с этим.
мне нравится этот метод:
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 + полей, из которых мне нужен был только идентификатор в качестве объекта строки списка. Я использовал 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()); }
Comments