Newtonsoft kullanarak JSON to .NET nesnesi serisini kaldırma (veya JSON için LINQ belki?)


318

Newtonsoft hakkında birkaç yazı olduğunu biliyorum, umarım bu tam olarak bir tekrar değildir ... Kazaa'nın API'sı tarafından döndürülen JSON verilerini bir tür güzel bir nesneye dönüştürmeye çalışıyorum

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

Bu JsonConvert hattı sadece denediğim en yeni hat ... Bunu tam olarak anlayamıyorum ve sizden bazı ayak işlerini ortadan kaldırmayı umuyordum. Başlangıçta bir sözlüğe ya da başka bir şeye dönüştürmeye çalışıyordum ... ve aslında, orada birkaç değer bulmaya ihtiyacım var, bu yüzden belgelere göre değerlendirmek, belki Newtonsoft'un LINQ'dan JSON'a daha iyi bir seçim olabilir mi? Düşünceler / Bağlantılar?

JSON dönüş verilerine bir örnek:

{
  "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
}

Biraz daha okuma yaptım ve Newtonsoft'un JSON'dan LINQ'sunun tam olarak istediğim olduğunu buldum ... WebClient, Stream, StreamReader ve Newtonsoft kullanarak ... JSON verileri için Kazaa'ya vurabilir, bir URL çıkarabilir, dosyayı indirebilir ve yapabilirim yedi kod satırı gibi! Onu seviyorum.

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

Bu yazı, yorumlarda tartışılan "kullanma" bitlerini eklemenin yararlı olabileceğini düşündüğüm çok sayıda isabet alıyor.

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

6
Kaygan bir örnek, teşekkürler. Sadece bir öneri: Eğer kısalık için bu off sol, ancak o zamandan beri olabilir WebClient, Streamve StreamReadertüm uygulamak IDisposablebazı eklemek isteyebilirsiniz, usingkodunuzu blokları.
arcain

ah evet, iyi çağrı ... (ya bu aslında sadece bir konsol uygulaması oldu Ben geldiğim görevler için araştırma için çok hızlı koşuyordu) Şimdi bulmacanın son parçası, HLS + AES şifreleme araştırmaya :) ugh ... lol
J Benjamin

1
+1 Linq örneğini gönderdiğiniz için teşekkür ederiz. Tam olarak ihtiyacım olan şey.
Mark Wilkins

Newtonsoft çözümü JSON'un tam olarak serisini kaldırmıyor mu? Tıpkı @ arcain'in çözümü gibi.
AXMIM

Buradaki bağlantıya dikkat edin: LINQ - JSON
yu yang Jian

Yanıtlar:


259

JSON nesnesinden birkaç öğe almanız gerekiyorsa, Json.NET'in LINQ to JSON JObjectsınıfını kullanırdım. Örneğin:

JToken token = JObject.Parse(stringFullOfJson);

int page = (int)token.SelectToken("page");
int totalPages = (int)token.SelectToken("total_pages");

Bu yaklaşımı seviyorum çünkü JSON nesnesinin tamamen serileştirilmesine gerek yok. Bu, Twitter gibi eksik nesne özellikleriyle sizi şaşırtabilecek API'lerle kullanışlı olur.

Dokümantasyon: JON.NET ile JSON'un serileştirilmesi ve serileştirilmesi ve Json.NET ile LINQ'dan JSON'a


1
ya Aslında biraz daha okuma ve test yaptım ... Bunu da bunu yapmanın güzel bir yolu olarak buldum ... Newtonsoft, oldukça güzel bir kütüphane, başkaları için örneğimi göndereceğim
J Benjamin

1
nasıl yaptığımı kabaca bir örnek gönderdi ... tam olarak aynı değil, JToken önerdiğini görüyorum.Parse ... henüz ikisi arasındaki farklar emin değilim ama iyi şeyler!
J Benjamin

1
@Jbenjamin Teşekkürler! Bu bir yazım hatasıydı. JToken, JObject için temel sınıftır ve daha soyut tiple çalışmak benim kişisel tercihim. Dikkatimi çektiğin için teşekkürler.
05

Üzgünüm, ama JToken veya JObject olmalı mı? Yukarıdaki kod hala arada bir "JsonReader JObject okuma hatası" hatası veriyor.
TYRONEMICHAEL

1
@Tyrone Tabii, sorun değil. Aslında bu kodu Twitter durum ayrıştırma için de kullanıyorum ve Twitter'a yapılan çağrıların etrafında zaman zaman sivilceli olabileceğinden biraz hata yazmak zorunda kaldım. Henüz yapmadıysanız, ayrıştırmaya çalışmadan önce ham JSON yanıtını Twitter'dan bir günlüğe dökmenizi öneririm. Sonra başarısız olursa, en azından tel üzerinden korkak bir şey alıp almadığınızı görebilirsiniz.
arcain

272

dynamicİşleri kolaylaştırmak için C # türünü kullanabilirsiniz. Bu teknik ayrıca sihirli dizelere bağlı olmadığı için yeniden faktoringi daha basit hale getirir.

JSON

Aşağıdaki JSON dizesi bir HTTP API çağrısından gelen basit bir yanıttır ve iki özelliği tanımlar: Idve Name.

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

C #

JsonConvert.DeserializeObject<dynamic>()Bu dizeyi dinamik bir türe serileştirmek için kullanın , daha sonra özelliklerine normal şekilde erişin.

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

Eğer türünü belirtirseniz resultsolarak değişken dynamickullanmak yerine, varanahtar kelime, daha sonra özellik değerleri doğru örn serisini olacak Idbir etmek intdeğil, bir JValue(yorumun altında için GFoley83 sayesinde).

Not : Newtonsoft montajı için NuGet bağlantısı http://nuget.org/packages/newtonsoft.json şeklindedir .

Paket : Ayrıca nuget live installer ile paketi ekleyebilirsiniz, projeniz açıldığında sadece göz atma paketini kurun ve ardından yükleyin, yükleyin, unistall, güncelleme , sadece Bağımlılıklar / NuGet altında projenize eklenecektir


Ben newtonsoft.dll sürüm 4.5.6 ile twitter yanıtı serpiştirmek için yukarıdaki gibi aynı kod parçası kullanıyordum ve iyi çalışıyordu .. ama sürüm 5.0.6 güncelledikten sonra .. hata atmaya başladı ... herhangi bir fikir neden ??
Pranav

1
Dinamik nesne için iyi, bildiğimizde veya c # sınıfımız olduğunda, dinamik değişimin yerine C # sınıfı olarak tüketebiliriz, örneğin <Myclass>.
MSTdev

2
dynamic results = JsonConvert.DeserializeObject<ExpandoObject>(json);Burada FTW kullanın . IdBir int yerine doğru bir şekilde serileştirmeyi kaldırır JValue. Buraya bakın: dotnetfiddle.net/b0WxGJ
GFoley83

@biofractal Bunu VB.NET'te nasıl yapabilirim dynamic results = JsonConvert.DeserializeObject<dynamic>(json); ? Dim results As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Object)(json)çalışmıyor.
Flo,


41

İle dynamicanahtar kelime, bu tür herhangi bir nesne ayrıştırmak için gerçekten çok kolay hale gelir:

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

Ben sonuçları arasında döngü nasıl bilmek istedim ve bu bulmak için çok uzun sürdü ... teşekkürler !!
batoutofhell

22

Yanılıyorsam beni düzeltin, ancak önceki örnek, sanırım, James Newton'un Json.NET kütüphanesinin en son sürümüyle biraz senkronize değil.

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

1
cevabınız için teşekkürler Rick, ya da en son belgelerde bulduğum örneklere benziyor.
J Benjamin

1
Evet, arcain yazım hatasını düzelttiğinden, yorumum şimdi sadece nitpicky görünüyor: '(. Başlangıçta JToken.Parse'yi tanımadığım için gönderdim.
Rick Leitch

1
Hiç nitpicky Değil - Kesinlikle orada oldu bir hata, ve bunu yapmak için birden fazla yolu her zaman vardır. Bu arada, Json.NET sürümüm dizin oluşturucuyu kullanarak sözdizimini destekliyor JObject, ancak cevabım için değiştirdiğim kod, kodun aşırı yüklenmesini kullanarak koddan çekildi, SelectTokenböylece simge olmasaydı istisnaları bastırabiliyordum. bulundu:, JToken JToken.SelectToken(string tokenName, bool errorWhenNoMatch)bu yüzden ayrıntı düzeyi geldi.
arcain

18

Benim gibi, güçlü yazılan nesnelerle uğraşmayı tercih ediyorsanız **:

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

Bu şekilde intellisense kullanmak ve zaman tipi hata kontrolü derlemek.

JSON'unuzu belleğe kopyalayıp JSON nesneleri olarak yapıştırarak gerekli nesneleri kolayca oluşturabilirsiniz (Visual Studio -> Düzenle -> Özel Yapıştır -> JSON'u Sınıf Olarak Yapıştır).

Visual Studio'da bu seçeneğe sahip değilseniz buraya bakın .

Ayrıca JSON'unuzun geçerli olduğundan emin olmanız gerekir. Yalnızca bir nesne dizisiyse başlangıçta kendi nesnenizi ekleyin. yani { "obj": [{}, {}, {}]}

** Bunu biliyorum dinamik kolay Bazen bazı şeyleri yapar ama bununla biraz ol'skool değilim.


1
Programlamaya tercih ettiğim çok şeydi. Güçlü yazım nesnelerini seviyorum. Teşekkürler, çünkü bu kodu kullandım ve değiştirdim.
j.hull

11

Dinamik Liste Gevşek Yazılmış - Değerlerin serisini kaldır ve oku

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

Bu yöntemi seviyorum:

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

Artık dictObjsözlük olarak kullanarak istediğiniz her şeye erişebilirsiniz . Dictionary<string, string>Değerleri dize olarak almayı tercih ediyorsanız da kullanabilirsiniz .

Herhangi bir .NET nesnesi olarak yayınlamak için aynı yöntemi kullanabilirsiniz.


2
Bu yöntemi iki nedenden dolayı çok güzel buluyorum: 1) veri türünü (her şey dize) umursamadığınızda ve 2) değerlerin bir sözlüğü ile çalışmak uygundur
netfed

7

Ayrıca, yalnızca JSON içeriğinde yuvalanmış belirli bir değer arıyorsanız şöyle yapabilirsiniz:

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

Ve böylece oradan devam edin.

Tüm JSON'u bir C # nesnesine dönüştürme maliyetini taşımak istemiyorsanız bu yardımcı olabilir.


2

json için bir Extionclass craeted:

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

Tasarım-Desen:

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

Kullanımı:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);


1

Bu partiye oldukça geç kaldım, ama bugün bu konuda kendimle karşılaştım. Sorunu şu şekilde çözdüm.

Bir kitap listesi almak için üçüncü taraf bir API'ya erişiyordum. Nesne yaklaşık 20+ alan içeren devasa bir JSON nesnesi döndürdü, bunlardan sadece ID'yi bir List string nesnesi olarak ihtiyacım vardı. Dinamik nesne üzerinde gerekli belirli alanı almak için linq kullandım ve sonra benim Liste dize nesnesine ekledi.

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

0

Sonunda Eyalet Adını JSON'dan Alın

Teşekkür ederim!

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.