Việc khử lưu lượng đối tượng JSON thành .NET bằng cách sử dụng Newtonsoft (hoặc có thể LINQ thành JSON?)


318

Tôi biết có một vài bài viết về Newtonsoft vì vậy hy vọng điều này không chính xác lặp lại ... Tôi đang cố gắng chuyển đổi dữ liệu JSON được trả về bởi API của Kazaa thành một đối tượng tốt đẹp nào đó

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

Dòng JsonConvert đó chỉ là dòng gần đây nhất mà tôi đã thử ... Tôi không hoàn toàn hiểu được nó và hy vọng sẽ loại bỏ một số bước chân bằng cách hỏi các bạn. Ban đầu tôi đã cố gắng chuyển đổi nó thành một cuốn Từ điển hoặc một cái gì đó ... và thực sự, tôi chỉ cần chọn một vài giá trị trong đó để đánh giá bằng tài liệu, có lẽ LINQ của Newtonsoft thành JSON có thể là lựa chọn tốt hơn? Suy nghĩ / Liên kết?

Dưới đây là một ví dụ về dữ liệu trả về 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
}

Tôi đã đọc thêm và thấy LINQ của Newtonsoft với JSON chính xác là những gì tôi muốn ... bằng cách sử dụng WebClient, Stream, StreamReader và Newtonsoft ... Tôi có thể nhấn Kazaa cho dữ liệu JSON, trích xuất URL, tải xuống tệp và thực hiện Tất cả giống như bảy dòng mã! Tôi thích nó.

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

Bài đăng này nhận được rất nhiều lượt truy cập Tôi nghĩ rằng nó có thể hữu ích để bao gồm các bit "sử dụng" được thảo luận trong các bình luận.

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
Ví dụ khéo léo, cảm ơn. Chỉ cần một gợi ý: bạn có thể đã rời đi này cho ngắn gọn, nhưng kể từ WebClient, StreamStreamReadertất cả thực hiện IDisposable, bạn có thể muốn thêm một số usingkhối để mã của bạn.
Arcain

à vâng, cuộc gọi tốt ... (ya đây thực sự chỉ là một ứng dụng console mà tôi đang chạy rất nhanh để nghiên cứu cho các nhiệm vụ tôi sắp làm) Bây giờ hãy nghiên cứu phần cuối của câu đố, mã hóa HLS + AES :) ugh ... lol
J Benjamin

1
+1 Cảm ơn bạn đã đăng ví dụ Linq. Chính xác những gì tôi cần.
Mark Wilkins

Có phải giải pháp newtonsoft cũng không giải thích hoàn toàn JSON? Giống như giải pháp của @ arcain.
AXMIM

Lưu ý liên kết tại đây: LINQ to JSON
yu yang Jian

Câu trả lời:


259

Nếu bạn chỉ cần lấy một vài mục từ đối tượng JSON, tôi sẽ sử dụng JObjectlớp LINQ to JSON của Json.NET . Ví dụ:

JToken token = JObject.Parse(stringFullOfJson);

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

Tôi thích cách tiếp cận này vì bạn không cần phải giải tuần hoàn hóa đối tượng JSON. Điều này rất hữu ích với các API đôi khi có thể làm bạn ngạc nhiên với các thuộc tính đối tượng bị thiếu, như Twitter.

Tài liệu: Tuần tự hóa và giải tuần tự hóa JSON với Json.NETLINQ thành JSON với Json.NET


1
ya Tôi thực sự đã đọc và kiểm tra nhiều hơn một chút ... thấy rằng đây cũng là một cách hay để làm điều đó ... Newtonsoft, thư viện khá đẹp, tôi sẽ đăng ví dụ của mình cho người khác
J Benjamin

1
đã đăng một ví dụ sơ bộ về cách tôi đang làm nó ... không hoàn toàn giống nhau, tôi thấy bạn đã đề xuất JToken.Pude ... không chắc chắn về sự khác biệt giữa hai người nhưng ya, thứ tốt!
J Benjamin

1
@Jbenjamin Cảm ơn! Đó là một lỗi đánh máy. JToken là lớp cơ sở cho JObject và đó chỉ là sở thích cá nhân của tôi để làm việc với loại trừu tượng hơn. Cảm ơn đã gọi đó để tôi chú ý.
Arcain

Xin lỗi, nhưng nó nên là JToken, hay JObject? Đoạn mã trên vẫn đang xuất hiện lỗi "Lỗi đọc JObject từ JsonReader" mọi lúc mọi nơi.
TYRONEMICHAEL

1
@Tyrone Chắc chắn, không vấn đề gì. Tôi thực sự cũng sử dụng mã này để phân tích trạng thái Twitter và tôi đã phải viết khá nhiều lỗi xử lý xung quanh các cuộc gọi tới Twitter vì đôi khi chúng có thể bị phát hiện. Nếu bạn chưa làm như vậy, tôi khuyên bạn nên bỏ phản hồi JSON thô từ Twitter vào nhật ký trước khi thử phân tích cú pháp. Sau đó, nếu nó thất bại, ít nhất bạn có thể xem nếu bạn nhận được một cái gì đó sôi nổi qua dây.
Arcain

272

Bạn có thể sử dụng loại C # dynamicđể làm cho mọi thứ dễ dàng hơn. Kỹ thuật này cũng làm cho việc bao thanh toán trở nên đơn giản hơn vì nó không dựa vào chuỗi ma thuật.

JSON

Chuỗi JSON bên dưới là một phản hồi đơn giản từ lệnh gọi API HTTP và nó xác định hai thuộc tính: IdName.

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

C #

Sử dụng JsonConvert.DeserializeObject<dynamic>()để giải tuần tự chuỗi này thành một kiểu động sau đó chỉ cần truy cập các thuộc tính của chuỗi theo cách thông thường.

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

Nếu bạn chỉ định loại resultsbiến là dynamic, thay vì sử dụng vartừ khóa, thì các giá trị thuộc tính sẽ khử lưu chính xác, ví dụ như Idmột intvà không phải JValue(nhờ vào GFoley83 cho nhận xét bên dưới).

Lưu ý : Liên kết NuGet cho lắp ráp Newtonsoft là http://nuget.org/packages/newtonsoft.json .

Gói : Bạn cũng có thể thêm gói với trình cài đặt trực tiếp nuget, với dự án của bạn được mở chỉ cần thực hiện gói duyệt và sau đó chỉ cần cài đặt, cài đặt, cập nhật , nó sẽ được thêm vào dự án của bạn trong Dependencies / NuGet


Tôi đã sử dụng cùng một đoạn mã như trên để giải tuần tự hóa phản hồi twitter với newtonsoft.dll phiên bản 4.5.6 và nó đã hoạt động tốt .. nhưng sau khi cập nhật lên phiên bản 5.0.6 .. nó bắt đầu ném lỗi ... mọi ý tưởng tại sao ??
Pranav

1
Tốt cho đối tượng động, khi chúng tôi biết hoặc chúng tôi có lớp c # để chúng tôi có thể sử dụng làm lớp C # thay thế cho động, ví dụ: <Mygroup>.
MSTdev

2
Sử dụng dynamic results = JsonConvert.DeserializeObject<ExpandoObject>(json);ở đây FTW. Nó sẽ giải thích chính xác Idđến một int chứ không phải a JValue. Xem tại đây: dotnetfiddle.net/b0WxGJ
GFoley83

@biofractal Làm thế nào để tôi làm điều này dynamic results = JsonConvert.DeserializeObject<dynamic>(json); trong VB.NET? Dim results As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Object)(json)không hoạt động.
Flo


41

Với dynamictừ khóa, thật dễ dàng để phân tích bất kỳ đối tượng nào thuộc loại này:

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

Tôi muốn biết làm thế nào để lặp lại kết quả và điều này mất quá nhiều thời gian để tìm ... cảm ơn !!
batoutofhell

22

Sửa lỗi cho tôi nếu tôi nhầm, nhưng ví dụ trước đây, tôi tin rằng, chỉ hơi không đồng bộ với phiên bản mới nhất của thư viện Json.NET của James Newton.

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

1
cảm ơn phản hồi của bạn Rick, ya trông giống như các ví dụ tôi tìm thấy trong tài liệu gần đây nhất.
J Benjamin

1
Vâng, vì arcain đã sửa lỗi chính tả, nhận xét của tôi bây giờ trông có vẻ khó chịu: '(. Ban đầu tôi đã đăng vì tôi không nhận ra JToken.Pude.
Rick Leitch

1
Không nitpicky ở tất cả - đó chắc chắn một sai lầm, và luôn có nhiều hơn một cách để làm điều đó. Nhân tiện, phiên bản Json.NET của tôi hỗ trợ cú pháp bằng cách sử dụng bộ chỉ mục trên JObject, nhưng mã tôi đã sửa đổi cho câu trả lời của tôi được lấy từ mã sử dụng quá tải SelectTokenphương thức để tôi có thể loại bỏ ngoại lệ nếu mã thông báo không tìm thấy JToken JToken.SelectToken(string tokenName, bool errorWhenNoMatch):, đó là nơi mà sự dài dòng đến từ.
Arcain

18

Nếu, giống như tôi, bạn thích đối phó với các đối tượng được gõ mạnh ** đi với:

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

Bằng cách này bạn có thể sử dụng kiểm tra lỗi loại thời gian intellisense và biên dịch.

Bạn có thể dễ dàng tạo các đối tượng cần thiết bằng cách sao chép JSON của mình vào bộ nhớ và dán nó dưới dạng đối tượng JSON (Visual Studio -> Chỉnh sửa -> Dán đặc biệt -> Dán JSON dưới dạng các lớp).

Xem ở đây nếu bạn không có tùy chọn đó trong Visual Studio.

Bạn cũng sẽ cần đảm bảo JSON của bạn hợp lệ. Thêm đối tượng của riêng bạn khi bắt đầu nếu nó chỉ là một mảng các đối tượng. tức là { "obj": [{}, {}, {}]}

** Tôi biết rằng năng động đôi khi làm mọi thứ dễ dàng hơn nhưng tôi hơi khó chịu với điều này.


1
Rất nhiều ưa thích của tôi tiếp cận với lập trình. Tôi thích các đối tượng gõ mạnh. Cảm ơn, vì tôi đã sử dụng và sửa đổi mã này.
j.hull

11

Danh sách động được gõ lỏng lẻo - Giải nén và đọc các giá trị

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

Tôi thích phương pháp này:

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

Bây giờ bạn có thể truy cập bất cứ điều gì bạn muốn bằng cách sử dụng dictObj như một từ điển. Bạn cũng có thể dùngDictionary<string, string> nếu bạn muốn lấy các giá trị dưới dạng chuỗi.

Bạn có thể sử dụng cùng phương thức này để truyền như bất kỳ loại đối tượng .NET nào.


2
Tôi thấy phương pháp này rất hay vì hai lý do: 1) khi bạn không quan tâm đến kiểu dữ liệu (mọi thứ đều là chuỗi) và 2) thật tiện lợi khi làm việc với một từ điển các giá trị
netfed

7

Ngoài ra, nếu bạn chỉ tìm kiếm một giá trị cụ thể được lồng trong nội dung JSON, bạn có thể làm điều gì đó tương tự:

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

Và cứ thế từ đó.

Điều này có thể giúp ích nếu bạn không muốn chịu chi phí chuyển đổi toàn bộ JSON thành đối tượng C #.


2

tôi thèm một Extiongroup cho 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); }
}

Mẫu thiết kế:

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

Sử dụng:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);


1

Khá muộn cho bữa tiệc này, nhưng tôi đã gặp vấn đề này ngày hôm nay tại nơi làm việc. Đây là cách tôi giải quyết vấn đề.

Tôi đã truy cập API của bên thứ 3 để lấy danh sách sách. Đối tượng đã trả về một đối tượng JSON lớn chứa khoảng hơn 20 trường, trong đó tôi chỉ cần ID làm đối tượng chuỗi Danh sách. Tôi đã sử dụng linq trên đối tượng động để lấy trường cụ thể mà tôi cần và sau đó chèn nó vào đối tượng chuỗi List của tôi.

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

Cuối cùng, lấy tên trạng thái từ JSON

Cảm ơn bạn!

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.