2014-05-10 13 views
12

Chcę użyć ReadAsAsync() w moim projekcie mvc z .net 4.0. Wynik jest zerowy.Używanie ReadAsAsync <T>() do deserializacji złożonego obiektu Json

Gdybym wprowadzić URI zająć bar, wynik w chromie jak (nazwy zmiennych są zmienione):

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

Gdybym użyć instrukcji w kodzie:

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

wiadomość pochodzi w formacie ciąg jako "{\"MyListResponse\":{\"customerSessionId\"...}" odpowiadający obiekt jSON jako:

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

a właściwości result1 i result2 są wartościami pustymi lub domyślnymi. Definicje klas są poniżej. Chcę przeczytać treść jako obiekt, ale nie mogłem. Co radzisz rozwiązać? Co ja robię źle? Z góry dziękuję.

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

Odpowiedz

7

I określonych nowej klasy jak:

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

potem wykorzystywane to opakowanie o,

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

to działało. Potrzebuję tylko obiektu MySummary, ale powinienem napisać więcej klas, żeby to działało.

6

Po przeczytaniu swoje rozwiązanie wpadłem na taki, który nie wymaga dodatkowego Klasa:

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

Możesz uprościć to jeszcze bardziej 'output = oczekiwać na odpowiedź.Content.ReadAsAsync ();' ' – Nkosi

3

Dla przyszłych czytelników, myślę, że właściwym podejściem jest użycie ReadAsAsync przeciążenie, że trwa IEnumerable<MediaTypeFormatter> i zapewniają formatyzator z tymi samymi ustawieniami, które są używane na serwerze do serializacji. To powinno to naprawić.

0

Możliwe jest korzystanie bezpośrednio z klienta ReadAsAsync z MyListResponse bezpośrednio (w konsekwencji bez ResponseWrapper). Aby to zrobić, możesz zdefiniować "BodyStyle = WebMessageBodyStyle.Bare" w umowie operacyjnej "apiuri" zamiast "BodyStyle = WebMessageBodyStyle.Wrapped" (po stronie serwera, tj. Umowy serwisowej).

Powiązane problemy