【问题标题】:Using ReadAsAsync<T>() to deserialize complex Json object使用 ReadAsAsync<T>() 反序列化复杂的 Json 对象
【发布时间】:2014-05-10 03:17:08
【问题描述】:

我想在 .net 4.0 的 mvc 项目中使用 ReadAsAsync()。结果为空。

如果我在地址栏输入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":"...",
             .
             .
            }
        }
    }
 } 

result1 和 result2 的属性为 null 或默认值。 类定义如下。我想将内容作为对象阅读,但我不能。你有什么建议来解决这个问题?我究竟做错了什么?提前致谢。

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

【问题讨论】:

    标签: asp.net-mvc-4 .net-4.0 httpclient


    【解决方案1】:

    我定义了一个新类:

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

    然后我使用了这个包装器,

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

    然后它起作用了。我只需要 MySummary 对象,但我应该编写更多类来使其工作。

    【讨论】:

      【解决方案2】:

      阅读您的解决方案后,我想出了一个不需要额外课程的解决方案:

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

      【讨论】:

      • 你可以进一步简化这个output = await response.Content.ReadAsAsync&lt;U&gt;();
      • @Nkosi 这在我的情况下不起作用,因为默认情况下ReadAsAsync 调用不处理蛇案例,它会出现。然后您必须将设置发送到DeserializeObject(或找出原因默认情况下不解析)。
      【解决方案3】:

      为了未来的读者,我认为正确的方法是使用 ReadAsAsync 重载,它采用 IEnumerable&lt;MediaTypeFormatter&gt; 并提供一个格式化程序,该格式化程序与服务器上用于序列化的设置相同。那应该可以解决它。

      【讨论】:

        【解决方案4】:

        可以在客户端 ReadAsAsync 直接与 MyListResponse 一起使用(因此没有 ResponseWrapper)。为此,您可以在“apiuri”的操作契约中定义“BodyStyle = WebMessageBodyStyle.Bare”,而不是“BodyStyle = WebMessageBodyStyle.Wrapped”(服务器端,即服务契约)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多