Използване на ReadAsAsync‹T›() за десериализация на сложен Json обект

Искам да използвам ReadAsAsync() в моя mvc проект с .net 4.0. Резултатът е нулев.

Ако въведа uri адресната лента, резултатът в chrome като (имената на таговете се променят):

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

Ако използвам израза в кода:

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

съобщението идва във формат на низ като "{\"MyListResponse\":{\"customerSessionId\"...}", което съответства на json обект като:

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

и свойствата на резултат1 и резултат2 са нулеви или стойности по подразбиране. Дефинициите на класа са по-долу. Искам да прочета съдържанието като обект, но не можах. Какво съветвате за разрешаване на това? какво правя грешно Благодаря предварително.

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

person serefbilge    schedule 10.05.2014    source източник


Отговори (4)


Дефинирах нов клас като:

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

след това използвах тази обвивка с,

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

тогава проработи. Имам нужда само от обект MySummary, но трябва да напиша повече класове, за да работи.

person serefbilge    schedule 11.05.2014

След като прочетох вашето решение, измислих такова, което не се нуждае от допълнителен клас:

    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;
    }
person RoboJ1M    schedule 23.07.2014
comment
Можете да опростите това още повече output = await response.Content.ReadAsAsync<U>(); - person Nkosi; 06.01.2017
comment
@Nkosi Това не работи в моя случай, тъй като извикването ReadAsAsync не обработва регистъра на змийските букви по подразбиране, изглежда. След това трябва да изпратите настройки на DeserializeObject (или да разберете защо не се анализира по подразбиране). - person ruffin; 22.03.2019

В името на бъдещите читатели, мисля, че правилният подход е използването на ReadAsAsync претоварване, което отнема IEnumerable<MediaTypeFormatter> и осигурява форматиране със същите настройки, използвани на сървъра за сериализиране. Това трябва да го оправи.

person Jony Adamit    schedule 06.05.2015

Възможно е да се използва на клиента ReadAsAsync с MyListResponse директно (в резултат без ResponseWrapper). За да направите това, можете да дефинирате „BodyStyle = WebMessageBodyStyle.Bare“ в договора за работа на „apiuri“ вместо „BodyStyle = WebMessageBodyStyle.Wrapped“ (от страна на сървъра, т.е. договор за услуга).

person Moises Quintero Orea    schedule 08.03.2016