Làm cách nào tôi có thể phân tích JSON bằng C #?


455

Tôi có đoạn mã sau:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

Đầu vào trong responsecontentlà JSON, nhưng nó không được phân tích cú pháp chính xác thành một đối tượng. Làm thế nào tôi nên khử lưu huỳnh đúng cách?


7
Xin chào, bạn có thể muốn thử liên kết này techblog.procurios.nl/k/n618/news/view/14605/14863/ trộm
Vamsi

34
Jsontrong System.Web.Helpers, có JsonQueryStringConvertertrong System.ServiceModel.Web, có JavascriptSerializertrong System.Web.Script.Serialization, DataContractJsonSerializertrong System.Runtime.Serialization.Json, quái MS thậm chí đã quyết định bao gồm bên thứ ba Json.NETtrong API ASP.NET Web của nó. Nếu bạn nghĩ rằng điều đó là không đủ, MS sẽ xuất System.Jsonhiện nhưng hiện tại không phù hợp để tiêu thụ. Con đường để đi Microsoft con đường để đi .... Tôi chọn theo không gian tên tìm kiếm tốt nhất.
nawfal

4
@fusi phần còn lại nằm trong các hội đồng riêng biệt. Google không gian tên / tên lớp, bạn sẽ tìm thấy tập hợp chúng trong tài liệu msDN. Chỉ cần thêm tài liệu tham khảo cho hội đồng đó.
nawfal

1
Chỉ cần hoàn thành, cũng có JsonValuetrong Windows.Data.Jsonđó chỉ dành cho Windows 8 trở lên. Tôi đang yêu nó. MS đang thực hiện nhiệm vụ :)
nawfal

5
NewtonSoft có một trang so sánh trên trang web của họ (có thể sai lệch nhưng vẫn thú vị): newtonsoft.com/json/help/html/jsonnetvsdotnetserialulators.htmlm . Tôi đặc biệt thích hàng tuần tự từ điển vô nghĩa :)
Ohad Schneider

Câu trả lời:


365

Tôi giả sử bạn không sử dụng Json.NET (gói Newtonsoft.Json NuGet). Nếu đây là trường hợp, sau đó bạn nên thử nó.

Nó có các tính năng sau:

  1. LINQ sang JSON
  2. JsonSerializer để nhanh chóng chuyển đổi các đối tượng .NET của bạn thành JSON và quay lại
  3. Json.NET có thể tùy ý tạo JSON được định dạng tốt, thụt lề để gỡ lỗi hoặc hiển thị
  4. Các thuộc tính như JsonIgnore và JsonProperty có thể được thêm vào một lớp để tùy chỉnh cách một lớp được tuần tự hóa
  5. Khả năng chuyển đổi JSON sang và từ XML
  6. Hỗ trợ nhiều nền tảng: .NET, Silverlight và Compact Framework

Nhìn vào ví dụ dưới đây. Trong ví dụ này, JsonConvertlớp được sử dụng để chuyển đổi một đối tượng đến và từ JSON. Nó có hai phương thức tĩnh cho mục đích này. Họ là SerializeObject(Object obj)DeserializeObject<T>(String json):

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);

18
Tôi có thể giải tuần tự hóa một varbiến loại không, trong trường hợp tôi không biết cấu trúc hoàn chỉnh của mục tiêu của mình? Cụ thể, tôi đang sử dụng Rally User Story và tôi muốn chuyển đổi chúng thành các đối tượng.
Pedro Dusso

16
@VANDERWEYENJonathan - trong trình duyệt web hiện đại, JSON.parse (chuỗi) và JSON.opesify (đối tượng) đều xử lý ngày dưới dạng chuỗi ISO8601, là định dạng được mô tả trong câu trả lời ở trên. Bạn có thể muốn cập nhật tiêu chuẩn của mình trước khi mọi người quyết định nó không liên quan. Mọi người cần ngày nhiều hơn họ cần tiêu chuẩn của bạn.
Peter Wone

3
@PeterWone: Không, JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expirytrả về chuỗi "2008-12-28T00:00:00" , không phải ngày. nó có thể được biến thành một Datequa new Date(str), nhưng JSON.parsekhông biết gì về ngày tháng. Bạn sẽ phải chuyển qua một bộ thu hồi đã kiểm tra từng giá trị chuỗi theo một mẫu.
TJ Crowder

3
Vì 3.703 giây giống như 3 giây và 703ms và dấu phân cách là dấu thập phân tôi đặt cho bạn rằng đây là giây đến ba chữ số thập phân.
Peter Wone

38
Tại sao tất cả mọi người có vấn đề như vậy với bao gồm có liên quan require,include , importhoặc usingtuyên bố trong câu trả lời của họ. Điều đó có đau không?
Tomáš Zato - Phục hồi Monica

285

Như đã được trả lời ở đây - Deserialize JSON thành đối tượng động C #?

Nó khá đơn giản khi sử dụng Json.NET:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

Hoặc sử dụng Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

13
@MaxHodges, bạn nói đúng. Tôi chỉ sử dụng "chuỗi ma thuật" nội tuyến để trình bày cách phân tích các giá trị chuỗi JSON. Không muốn nó trông phức tạp với việc thoát dấu ngoặc kép. Trong mã thực, chúng ta thường có các chuỗi JSON thu được từ đâu đó dưới dạng các biến hoặc được truyền dưới dạng tham số.
Dmitry Pavlov

4
Không có .net 4, bạn không có từ khóa 'động'. Bạn có thể sử dụng 'var Stuff' để khai báo và thay vì 'Stuff.Name' và 'Stuff.Address.City' bạn có 'Stuff ["Name"]' và 'Stuff ["Địa chỉ"] ["City"]' .
Fil

1
@Fil Điều đó mang lại cho bạn một giá trị của loại objectvà bạn không thể sử dụng lập chỉ mục trên a object.
Alex

138

Dưới đây là một số tùy chọn mà không cần sử dụng thư viện của bên thứ ba:

// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());

// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);

Xem liên kết để biết thêm thông tin về System.Web.Helpers.Json .

Cập nhật : Ngày nay cách dễ nhất để có được Web.Helperslà sử dụng gói NuGet .


Nếu bạn không quan tâm đến các phiên bản Windows trước đó, bạn có thể sử dụng các lớp của Windows.Data.Jsonkhông gian tên:

// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());

Tại sao tôi không thấy System.Web.Helpers trong trang web ASP.NET của tôi (4.5)? XEuity, XPathSelectEuity không được biết đến với VisualStudio của tôi. Làm thế nào để giáo dục nó?
Budda

Vâng, bạn phải thêm tài liệu tham khảo cho các thư viện tương ứng (như được viết trong các ý kiến ​​ở trên), xem bài viết này để biết thêm. Ngoài ra, câu hỏi này có thể được quan tâm.
qqbenq

2
Tôi đã sử dụng phương pháp Web.Helpers được mô tả ở đây nhưng gặp phải một vấn đề đã được giải quyết bằng bài đăng này: stackoverflow.com/questions/7066726/ Kẻ
Alex

1
nó hoạt động với WPF.By bằng cách sử dụng không gian tên sau bằng System.R.78.Serialization.Json; sử dụng System.Xml.XPath; sử dụng System.Xml.Linq;
Shahid Neermunda

3
Json.Net hầu như không phải là thành phần của bên thứ ba nữa. Microsoft sử dụng nó những ngày này. Đây là trình biên dịch mặc định trên API Web.
Liam

62

Nếu .NET 4 có sẵn cho bạn, hãy xem: http://visitmix.com/writings/the-awn-of-json (archive.org)

Đây là một đoạn từ trang web đó:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

Cái Console cuối cùng đó.WriteLine khá ngọt ngào ...


Xin lỗi, có vẻ như mọi thứ đã thay đổi kể từ khi tôi trả lời ban đầu. Tôi sẽ phải nhìn xung quanh và xem thư viện nào là chính xác ...
ElonU Webdev

7
Mong bạn tìm được thư viện này. Chỉnh sửa: đây có phải là: Dynamicjson.codeplex.com không?
dùng989056

1
Tôi không biết ElonU có nghĩa là gì ở đây, nhưng có "JsonValue" trong Windows.Data.Json (chỉ dành cho Windows 8 trở lên - kỳ lạ) và cũng là "JsonValue" trong System.Json vẫn đang được xem trước và Chỉ có Chúa mới biết nó sẽ ra đời. MS làm tôi bối rối khi nói đến Json.
nawfal

35

Một giải pháp riêng khác cho vấn đề này, không yêu cầu bất kỳ thư viện của bên thứ 3 nào ngoài tham chiếu đến System.Web.Extensions là JavaScriptSerializer. Đây không phải là một tính năng mới nhưng rất chưa được biết đến từ 3.5.

using System.Web.Script.Serialization;

..

JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());

và quay lại

MyObject o = serializer.Deserialize<MyObject>(objectString)

2
Điều này rất hay, nhưng nó cần các cộng đồng web, vì vậy thật không may, nó không hoạt động trong .NET 4.0 Client Profile, đây là phiên bản .NET cuối cùng cho Windows XP. Có thể cài đặt đầy đủ .NET, nhưng nhiều người chỉ sử dụng Hồ sơ khách hàng. Ngược lại, System.R.78.Serialization.Json.DataContractJsonSerializer được hỗ trợ ngay cả trong Hồ sơ khách hàng.
Al Kepp 4/2/2015

3
@ fr34kyn01535: Windows XP có thị trường thứ hai trên máy tính để bàn. Nó có liên quan.
DonkeyMaster

Khi tôi sử dụng JavaScriptSerializer để khử dữ liệu đối tượng của mình, nó đã hoạt động nhưng nó đã khử lưu lượng ngày của tôi không chính xác. Đáng lẽ ra là 4/19/2018 12:00 AM nhưng được giải trừ đến 4/18/2018 08:00 PM. NewtonSoft.Json.JsonConvert đã giải tuần tự hóa nó như mong đợi.
Giàu


16

System.Json hoạt động ngay bây giờ ...

Cài đặt nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

Mẫu :

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

1
Cố gắng tìm một ví dụ về cách sử dụng chính xác Hệ thống hiện đại.Json đã đưa tôi đến đây, sau vô số kết quả cho Json.NET/Newtonsoft.Json/"Newtson.Json "và các lần lặp cũ hơn của System.Json từ lâu không được chấp nhận. Cảm ơn vì điều này.
khỉ0506

1
Điều này đã giúp tôi một cách rất lớn. Cảm ơn rât nhiều.
MAK

10

Sử dụng công cụ này để tạo một lớp dựa trên json của bạn:

http://json2csharp.com/

Và sau đó sử dụng lớp để khử lưu huỳnh của bạn. Thí dụ:

public class Account
{
    public string Email { get; set; }
    public bool Active { get; set; }
    public DateTime CreatedDate { get; set; }
    public IList<string> Roles { get; set; }
}


string json = @"{
  'Email': 'james@example.com',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

Account account = JsonConvert.DeserializeObject<Account>(json);

Console.WriteLine(account.Email);
// james@example.com

Tài liệu tham khảo: https://forums.asp.net/t/1992996.aspx?Nested+Json+Deserialization+to+C+object+and+USE+that+object https://www.newtonsoft.com/json/help /html/DeserializeObject.htm


9

Hãy thử đoạn mã sau:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}

Cảm ơn, tôi muốn phần ["result" + biến] vì tôi muốn sử dụng các biến được sử dụng ở đây mà bạn không thể dễ dàng thực hiện với JSON.NET.
PHPGuru

Dòng này có làm gì không ... JavaScriptSerializer js = new JavaScriptSerializer (); Cảm ơn trước.
Chris Catignani

9

System.Text.Json

.NET core 3.0 đi kèmSystem.Text.Json hợp có nghĩa là bạn có thể giải tuần tự hóa / tuần tự hóa JSON mà không cần sử dụng thư viện của bên thứ ba.

Để tuần tự hóa (các) lớp của bạn thành chuỗi JSON:

var json = JsonSerializer.Serialize(order);

Để giải tuần tự hóa JSON thành một lớp được gõ mạnh:

var order = JsonSerializer.Deserialize<Order>(json);

Vì vậy, nếu bạn có một lớp học như dưới đây:

public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public decimal Balance { get; set; }
    public DateTime Opened { get; set; }
}

var json = JsonSerializer.Serialize(order);
// creates JSON ==>
{
    "id": 123456,
    "orderNumber": "ABC-123-456",
    "balance": 9876.54,
    "opened": "2019-10-21T23:47:16.85",
};

var order = JsonSerializer.Deserialize<Order>(json);
// ==> creates the above class

Một điều cần lưu ý là System.Text.Json không tự động xử lýcamelCase các thuộc tính JSON khi sử dụng mã của riêng bạn (tuy nhiên, nó thực hiện khi sử dụng các yêu cầu MVC / WebAPI và chất kết dính mô hình).

Để giải quyết điều này, bạn cần phải vượt qua JsonSerializerOptionsnhư một tham số.

JsonSerializerOptions options = new JsonSerializerOptions
{        
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,  // set camelCase       
    WriteIndented = true                                // write pretty json
};

// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);

System.Text.Json cũng có sẵn cho .Net Framework và .Net Standard dưới dạng gói Nu-get System.Text.Json


1
Nếu bạn không có lớp thì sao? Điều gì sẽ xảy ra nếu bạn chỉ biết mơ hồ những gì dữ liệu json sẽ chứa? Hoặc nếu các khóa tồn tại?
Cherona

@Cherona sử dụng JsonDocument.Parse.
haldo

5

Tôi nghĩ rằng sau đây từ trang web msDN sẽ giúp cung cấp một số chức năng riêng cho những gì bạn đang tìm kiếm. Xin lưu ý rằng nó được chỉ định cho Windows 8. Một ví dụ như vậy từ trang web được liệt kê bên dưới.

JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");

Nó sử dụng không gian tên Windows.Data.JSON .


6
Đẹp, nhưng "Ứng dụng khách tối thiểu được hỗ trợ: Windows 8"
watbywbarif 10/03/2015

Tôi nghĩ rằng nó không còn được hỗ trợ nữa và bây giờ có newtonsoft json dll icouldnt find windows.data.json
virtouso

3
@virtouso, như watbywbarif chỉ ra rằng nó thực sự khá mới, tuy nhiên sự hỗ trợ tối thiểu từ Microsoft , chỉ hoạt động trong Windows 8.
TargetofGravity 13/03/2015

4

Bạn có thể sử dụng các mức độ sau đây

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}

0

Tôi nghĩ rằng câu trả lời tốt nhất mà tôi đã thấy là @MD_Sayem_Ahmed.

Câu hỏi của bạn là "Làm thế nào tôi có thể phân tích Json bằng C #", nhưng có vẻ như bạn đang muốn giải mã Json. Nếu bạn muốn giải mã nó, câu trả lời của Ahmed là tốt.

Nếu bạn đang cố gắng thực hiện điều này trong ASP.NET Web Api, cách dễ nhất là tạo một đối tượng truyền dữ liệu chứa dữ liệu bạn muốn gán:

public class MyDto{
    public string Name{get; set;}
    public string Value{get; set;}
}

Bạn chỉ cần thêm tiêu đề ứng dụng / json vào yêu cầu của bạn (ví dụ: nếu bạn đang sử dụng Fiddler). Sau đó, bạn sẽ sử dụng điều này trong ASP.NET Web API như sau:

//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
   MyDto someDto = myDto;
   /*ASP.NET automatically converts the data for you into this object 
    if you post a json object as follows:
{
    "Name": "SomeName",
      "Value": "SomeValue"
}
*/
   //do some stuff
}

Điều này đã giúp tôi rất nhiều khi tôi làm việc trong Web Api của tôi và làm cho cuộc sống của tôi trở nên siêu dễ dàng.


0
         string json = @"{
            'Name': 'Wide Web',
            'Url': 'www.wideweb.com.br'}";

        JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
        dynamic j = jsonSerializer.Deserialize<dynamic>(json);
        string name = j["Name"].ToString();
        string url = j["Url"].ToString();

-1
var result = controller.ActioName(objParams);
IDictionary<string, object> data = (IDictionary<string, object>)new System.Web.Routing.RouteValueDictionary(result.Data);
Assert.AreEqual("Table already exists.", data["Message"]);

2
Bạn giải thích tốt hơn giải pháp của bạn thay vì chỉ đăng một số hàng mã. Bạn có thể đọc Làm thế nào để tôi viết một câu trả lời tốt .
Massimiliano Kraus

Đừng quên đưa System.Webvào tài liệu tham khảo dự án của bạn.
Ohad Cohen

-3
 using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(user)))
 {
    // Deserialization from JSON  
    DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(UserListing))
    DataContractJsonSerializer(typeof(UserListing));
    UserListing response = (UserListing)deserializer.ReadObject(ms);

 }

 public class UserListing
 {
    public List<UserList> users { get; set; }      
 }

 public class UserList
 {
    public string FirstName { get; set; }       
    public string LastName { get; set; } 
 }
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.