2014-05-10 22 views
12

Tôi muốn sử dụng ReadAsAsync() trong dự án mvc của tôi với .net 4.0. Kết quả là null.Sử dụng ReadAsAsync <T>() để deserialize đối tượng Json phức tạp

Nếu tôi nhập uri thanh địa chỉ, kết quả trong chrome như (tên thẻ được thay đổi):

<ns2:MyListResponse xmlns:ns2="blablabla"> 
    <customerSessionId>xxcustomerSessionIdxx</customerSessionId> 
    <numberOfRecordsRequested>0</numberOfRecordsRequested> 
    <moreResultsAvailable>false</moreResultsAvailable> 
    <MyList size="1" activePropertyCount="1"> 
    <MySummary order="0"> 
     <id>1234</id> 
     <name>...</name> 
     . 
     . 
    </MySummary> 
    </MyList> 
</ns2:MyListResponse> 

Nếu tôi sử dụng câu lệnh trong mã:

using (var client = new HttpClient()) 
{ 
    var response = client.GetAsync(apiUri).Result; 
    var message = response.Content.ReadAsStringAsync().Result; 

    var result1 = JsonConvert.DeserializeObject<MyListResponse>(message); 
    var result2 = response.Content.ReadAsAsync<MyListResponse>().Result; 
} 

thông điệp đến ở định dạng chuỗi như "{\"MyListResponse\":{\"customerSessionId\"...}" tương ứng với một đối tượng jSON như:

{"MyListResponse": 
    {"customerSessionId":"xxcustomerSessionIdxx", 
    "numberOfRecordsRequested":0, 
    "moreResultsAvailable":false, 
    "MyList": 
     {"@size":"1", 
     "@activePropertyCount":"1", 
     "MySummary": 
      {"@order":"0", 
      "id":1234, 
      "name":"...", 
      . 
      . 
      } 
     } 
    } 
} 

và các thuộc tính của kết quả 1 và kết quả2 là các giá trị rỗng hoặc mặc định. Định nghĩa lớp học dưới đây. Tôi muốn đọc nội dung như một đối tượng nhưng tôi không thể. Bạn có lời khuyên nào để giải quyết vấn đề này? Tôi đang làm gì sai? Cảm ơn trước.

public class MySummary 
{ 
    public int @Order { get; set; } 
    public string Id { get; set; } 
    public string Name { get; set; } 
    . 
    . 
} 

public class MyList 
{ 
    public int @Size { get; set; } 
    public int @ActivePropertyCount { get; set; } 
    public MySummary MySummary{ get; set; } 
} 

public class MyListResponse 
{ 
    public string CustomerSessionId { get; set; } 
    public int NumberOfRecordsRequested { get; set; } 
    public bool MoreResultsAvailable { get; set; } 
    public MyList MyList { get; set; } 
} 

Trả lời

7

tôi định nghĩa một lớp mới như:

public class ResponseWrapper 
{ 
    public MyListResponse MyListResponse { get; set; } 
} 

sau đó tôi sử dụng wrapper này với,

var result1 = JsonConvert.DeserializeObject<ResponseWrapper>(message); 
var result2 = response.Content.ReadAsAsync<ResponseWrapper>().Result; 

sau đó nó làm việc. Tôi chỉ cần đối tượng MySummary nhưng tôi nên viết nhiều lớp hơn để làm cho nó hoạt động.

6

Sau khi đọc giải pháp của bạn tôi đã đưa ra một mà không cần một lớp học thêm:

private static async Task<U> Execute<U>(HttpClient client, string path) 
    { 
     U output = default(U); 

     HttpResponseMessage response = await client.GetAsync(path); 

     if (response.IsSuccessStatusCode) 
     { 
      var jsonAsString = await response.Content.ReadAsStringAsync(); 
      output = JsonConvert.DeserializeObject<U>(jsonAsString); 
     } 
     else 
     { 
      throw new ApplicationException(string.Format("Response message is not OK. Issues in action: {0}", path)); 
     } 

     return output; 
    } 
+1

Bạn có thể đơn giản hóa điều này hơn nữa 'output = await response.Content.ReadAsAsync ();' – Nkosi

3

Vì lợi ích của độc giả trong tương lai, tôi nghĩ rằng cách tiếp cận chính xác được sử dụng ReadAsAsync quá tải mà phải mất IEnumerable<MediaTypeFormatter> và cung cấp một trình định dạng có cùng cài đặt được sử dụng trên máy chủ để tuần tự hóa. Điều đó sẽ khắc phục nó.

0

Có thể sử dụng trực tiếp tại máy khách ReadAsAsync với MyListResponse (do hậu quả không có ResponseWrapper). Để làm điều này, bạn có thể xác định "BodyStyle = WebMessageBodyStyle.Bare" trong hợp đồng hoạt động của "apiuri" thay cho "BodyStyle = WebMessageBodyStyle.Wrapped" (phía máy chủ, nghĩa là hợp đồng dịch vụ).

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