2010-03-30 129 views
123

Tôi tương đối mới để làm việc với dữ liệu C# và JSON và đang tìm kiếm hướng dẫn. Tôi đang sử dụng C# 3.0, với .NET3.5SP1 và JSON.NET 3.5r6.Deserializing dữ liệu JSON để C# bằng cách sử dụng JSON.NET

Tôi có một lớp C# được xác định mà tôi cần phải điền từ một cấu trúc JSON. Tuy nhiên, không phải mọi cấu trúc JSON cho một mục nhập được lấy từ dịch vụ web đều chứa tất cả các thuộc tính có thể được định nghĩa trong lớp C#.

Tôi đã và đang làm những gì có vẻ là sai, khó và chỉ chọn từng giá trị một từ JObject và chuyển chuỗi thành thuộc tính lớp mong muốn.

JsonSerializer serializer = new JsonSerializer(); 
var o = (JObject)serializer.Deserialize(myjsondata); 

MyAccount.EmployeeID = (string)o["employeeid"][0]; 

Cách tốt nhất để deserialize cấu trúc JSON vào lớp C# và xử lý dữ liệu bị thiếu có thể có từ nguồn JSON là gì?

Lớp học của tôi được định nghĩa là:

public class MyAccount 
    { 

    [JsonProperty(PropertyName = "username")] 
    public string UserID { get; set; } 

    [JsonProperty(PropertyName = "givenname")] 
    public string GivenName { get; set; } 

    [JsonProperty(PropertyName = "sn")] 
    public string Surname { get; set; } 

    [JsonProperty(PropertyName = "passwordexpired")] 
    public DateTime PasswordExpire { get; set; } 

    [JsonProperty(PropertyName = "primaryaffiliation")] 
    public string PrimaryAffiliation { get; set; } 

    [JsonProperty(PropertyName = "affiliation")] 
    public string[] Affiliation { get; set; } 

    [JsonProperty(PropertyName = "affiliationstatus")] 
    public string AffiliationStatus { get; set; } 

    [JsonProperty(PropertyName = "affiliationmodifytimestamp")] 
    public DateTime AffiliationLastModified { get; set; } 

    [JsonProperty(PropertyName = "employeeid")] 
    public string EmployeeID { get; set; } 

    [JsonProperty(PropertyName = "accountstatus")] 
    public string AccountStatus { get; set; } 

    [JsonProperty(PropertyName = "accountstatusexpiration")] 
    public DateTime AccountStatusExpiration { get; set; } 

    [JsonProperty(PropertyName = "accountstatusexpmaxdate")] 
    public DateTime AccountStatusExpirationMaxDate { get; set; } 

    [JsonProperty(PropertyName = "accountstatusmodifytimestamp")] 
    public DateTime AccountStatusModified { get; set; } 

    [JsonProperty(PropertyName = "accountstatusexpnotice")] 
    public string AccountStatusExpNotice { get; set; } 

    [JsonProperty(PropertyName = "accountstatusmodifiedby")] 
    public Dictionary<DateTime, string> AccountStatusModifiedBy { get; set; } 

    [JsonProperty(PropertyName = "entrycreatedate")] 
    public DateTime EntryCreatedate { get; set; } 

    [JsonProperty(PropertyName = "entrydeactivationdate")] 
    public DateTime EntryDeactivationDate { get; set; } 

    } 

Và một mẫu của các JSON để phân tích cú pháp là:

{ 
    "givenname": [ 
     "Robert" 
    ], 
    "passwordexpired": "20091031041550Z", 
    "accountstatus": [ 
     "active" 
    ], 
    "accountstatusexpiration": [ 
     "20100612000000Z" 
    ], 
    "accountstatusexpmaxdate": [ 
     "20110410000000Z" 
    ], 
    "accountstatusmodifiedby": { 
     "20100214173242Z": "tdecker", 
     "20100304003242Z": "jsmith", 
     "20100324103242Z": "jsmith", 
     "20100325000005Z": "rjones", 
     "20100326210634Z": "jsmith", 
     "20100326211130Z": "jsmith" 
    }, 
    "accountstatusmodifytimestamp": [ 
     "20100312001213Z" 
    ], 
    "affiliation": [ 
     "Employee", 
     "Contractor", 
     "Staff" 
    ], 
    "affiliationmodifytimestamp": [ 
     "20100312001213Z" 
    ], 
    "affiliationstatus": [ 
     "detached" 
    ], 
    "entrycreatedate": [ 
     "20000922072747Z" 
    ], 
    "username": [ 
     "rjohnson" 
    ], 
    "primaryaffiliation": [ 
     "Staff" 
    ], 
    "employeeid": [ 
     "999777666" 
    ], 
    "sn": [ 
     "Johnson" 
    ] 
} 

Trả lời

70

Bạn đã cố gắng sử dụng các phương pháp DeserializeObject chung chung?

JsonConvert.DeserializeObject<MyAccount>(myjsondata); 

Bất kỳ trường bị thiếu nào trong dữ liệu JSON chỉ nên bỏ qua NULL.

UPDATE:

Nếu chuỗi JSON là một mảng, hãy thử này:

var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata); 

jarray sau đó phải là một List<MyAccount>.

KHÁC UPDATE:

Trường hợp ngoại lệ bạn đang nhận được là không phù hợp với một loạt các objects- Tôi nghĩ rằng serializer đang gặp vấn đề với từ điển, đánh máy accountstatusmodifiedby tài sản của bạn.

Hãy thử loại trừ thuộc tính accountstatusmodifiedby khỏi việc tuần tự hóa và xem điều đó có hữu ích không. Nếu có, bạn có thể cần phải đại diện cho thuộc tính đó khác nhau.

Tài liệu: Serializing and Deserializing JSON with Json.NET

+0

Cảm ơn. Tuy nhiên tôi nhận được một lỗi "Không thể deserialize JSON mảng vào loại 'System.String'." khi nó cố gắng deserialize (ví dụ) mảng JSON givenname vào chuỗi GivenName của lớp. Các thuộc tính JSON mà tôi đã định nghĩa là chuỗi trong lớp C# chỉ là các mảng phần tử đơn lẻ. Đây là lý do tại sao tôi bắt đầu chọn ra các giá trị từng cái một khi tôi gặp phải vấn đề này trong quá trình deserialize. Ma thuật khác mà tôi đang nhìn? –

+0

câu trả lời được cập nhật ... –

+0

Vì vậy ... 'DateTime AccountStatusExpiration' (ví dụ) không phải là nullable như được định nghĩa trong mã. Nó sẽ làm gì để làm cho nó vô hiệu? Chỉ cần thay đổi 'DateTime' thành' DateTime? '? –

8

Bạn có thể sử dụng:

JsonConvert.PopulateObject(json, obj); 

đây: json là chuỗi json, obj là đối tượng mục tiêu.Xem: example

Lưu ý: PopulateObject() sẽ không xóa dữ liệu danh sách obj, sau khi Populate(), obj's thành viên danh sách sẽ chứa dữ liệu gốc và dữ liệu từ chuỗi json

+2

PopulateObject - Populate không nằm trong mô hình đối tượng. – amok

+0

Không hoạt động trong các đối tượng C# phức tạp. – SutharMonil

+1

Điều này làm việc hoàn hảo cho tôi! Tôi đã gặp vấn đề mà tôi có một chuỗi JSON khá phức tạp, khi tôi cố gắng đưa nó vào các đối tượng C#, bất cứ thứ gì được đánh dấu là 'NotNull' sẽ bị thiếu trong đối tượng, mặc dù nó có trong chuỗi JSON để bắt đầu. Rất lạ. Tôi đã sử dụng phương pháp này và nó đã hoạt động HOÀN THÀNH! – jward01

256

Sử dụng JsonConvert.DeserializeObject<RootObject>(string json);

Tạo lớp học của bạn trên JSON 2 C#


Tài liệu Json.NET: Serializing and Deserializing JSON with Json.NET

+27

Visual Studio cũng có tùy chọn Dán JSON dưới dạng Lớp trong trình đơn Đặc biệt Chỉnh sửa Dán. –

0

Giả sử dữ liệu mẫu của bạn là chính xác, tên đã cho của bạn và các mục nhập khác được đặt trong ngoặc là các mảng trong JS ... bạn sẽ muốn sử dụng Danh sách cho các loại dữ liệu đó. và Danh sách cho biết accountstatusexpmaxdate ... Tôi nghĩ rằng bạn ví dụ có những ngày không chính xác định dạng mặc dù, do đó không chắc chắn như những gì khác là không chính xác trong ví dụ của bạn.

Đây là một bài đăng cũ nhưng muốn ghi lại các vấn đề.

1

Bạn có thể thử kiểm tra một số trình tạo lớp trực tuyến để biết thêm thông tin. Tuy nhiên, tôi tin rằng một số câu trả lời có ích. Đây là cách tiếp cận của tôi có thể hữu ích.

Đoạn mã sau được tạo bằng phương pháp động.

dynObj = (JArray)JsonConvert.DeserializeObject(nvm); 

     foreach (JObject item in dynObj) 
     { 
      foreach (JObject trend in item["trends"]) 
      { 
     Console.WriteLine("{0}-{1}-{2}", trend["query"], trend["name"], trend["url"]); 

      } 
     } 

Mã này về cơ bản cho phép bạn truy cập các thành viên có trong chuỗi Json. Chỉ là một cách khác mà không cần các lớp học. query, trendurl là các đối tượng có trong chuỗi Json.

Bạn cũng có thể sử dụng this website. Đừng tin tưởng các lớp học một 100% nhưng bạn có được ý tưởng.

45

trả lời sao chép từ https://stackoverflow.com/a/10718128/776476

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

Json

Chuỗi json dưới đây là một phản ứng đơn giản từ một cuộc gọi http api và nó định nghĩa hai thuộc tính: IdName.

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

C#

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

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

Note: Liên kết NuGet cho lắp ráp NewtonSoft là http://nuget.org/packages/newtonsoft.json. Đừng quên thêm: using Newtonsoft.Json; để truy cập các lớp đó.

+5

Yêu thích việc sử dụng . Tuy nhiên, tôi đã phải làm điều này để làm cho nó hoạt động: kết quả ["Id"] .Giá trị và kết quả ["Tên"] Giá trị – fredw

+0

Mặc dù động là một lựa chọn tốt đẹp, các ví dụ trên không sử dụng 'chuỗi ma thuật' nhưng thay vào đó sử dụng generics gõ mạnh mẽ được cập nhật trong các kỹ thuật tái cấu trúc VS bình thường (trừ khi bên trong một View trong MVC nằm ngoài phạm vi của câu hỏi này). – gcoleman0828

+1

Bạn vẫn có 'chuỗi ma thuật', giờ đây chúng chỉ bị ẩn bởi việc sử dụng năng động! –

3

Xây dựng câu trả lời của bbant, đây là giải pháp hoàn chỉnh để deserializing JSON của tôi từ một URL từ xa.

using Newtonsoft.Json; 
using System.Net.Http; 

namespace Base 
{ 
    public class ApiConsumer<T> 
    { 
     public T data; 
     private string url; 

     public CalendarApiConsumer(string url) 
     { 
      this.url = url; 
      this.data = getItems(); 
     } 

     private T getItems() 
     { 
      T result = default(T); 
      HttpClient client = new HttpClient(); 

      // This allows for debugging possible JSON issues 
      var settings = new JsonSerializerSettings 
      { 
       Error = (sender, args) => 
       { 
        if (System.Diagnostics.Debugger.IsAttached) 
        { 
         System.Diagnostics.Debugger.Break(); 
        } 
       } 
      }; 

      using (HttpResponseMessage response = client.GetAsync(this.url).Result) 
      { 
       if (response.IsSuccessStatusCode) 
       { 
        result = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result, settings); 
       } 
      } 
      return result; 
     } 
    } 
} 

Cách sử dụng sẽ như thế nào:

ApiConsumer<FeedResult> feed = new ApiConsumer<FeedResult>("http://example.info/feeds/feeds.aspx?alt=json-in-script"); 

đâu FeedResult là lớp được tạo ra bằng cách sử dụng Xamasoft JSON Class Generator

Đây là một ảnh chụp màn hình của các thiết lập tôi đã sử dụng, cho phép tên thuộc tính kỳ lạ đó web version không thể giải thích.

Xamasoft JSON Class Generator

1

Tôi phát hiện thấy mình đã xây dựng đối tượng không chính xác. Tôi đã sử dụng http://json2csharp.com/ để tạo cho tôi lớp đối tượng của tôi từ JSON. Một khi tôi đã có Oject chính xác tôi đã có thể cast mà không có vấn đề. Norbit, Noob nhầm lẫn. Nghĩ rằng tôi sẽ thêm nó trong trường hợp bạn có cùng một vấn đề.

Các vấn đề liên quan