在C#中从Web检索匿名类型

时间:2013-08-01 08:08:13

标签: c# xml json

我正在尝试从网上检索一些数据。数据以JSON对象或XML形式提供:在这两种情况下,我都希望不基于此XML / JSON的结构构建模型,而只是检索我需要的数据。

HttpResponseMessage response = await client.PostAsync(
"http://www.someAPI.com/api.xml",
requestContent);

response.EnsureSuccessStatusCode();

HttpContent content = response.Content;

如果我必须根据我收到的数据结构构建模型,我会这样做:我只是想知道是否有其他选择。我可以将content解析为匿名类型,并将数据检索为任意字段或属性或数组索引吗?

让我们说:response.Countries[5].CountryId。是否有可能在这两种类型(JSON和XML)中的任何一种?我该怎么办?

2 个答案:

答案 0 :(得分:18)

编辑#2:

我在下面添加了一条关于使用优秀的Json.NET库反序列化为dynamic对象的说明。


编辑#1:

感谢Hoghweed's answer,我的答案现在更完整了。具体来说,我们需要投射我们从HttpContentExpandoObjectHttpResponseMessage.Content,以便dynamic - ness按预期工作:< / p>

dynamic content = response.Content.ReadAsAsync<ExpandoObject>().Result;
var myPropertyValue = content.MyProperty;

要获得ReadAsync<T>()扩展方法,您需要使用NuGetMicrosoft.AspNet.WebApi.Client包(here's the "old" Nuget page)下载并安装System.Net.Http.Formatting.dll,它提到它现在包含在上述包中。)


原始答案:

因此,您不希望创建POCO并且必须将其属性作为XML / JSON结构进行管理。 dynamic似乎非常适合您的用例:

HttpResponseMessage response = await client.PostAsync(
"http://www.someAPI.com/api.xml", requestContent);

response.EnsureSuccessStatusCode();

dynamic content = response.Content.ReadAsAsync<ExpandoObject>().Result; // Notice the use of the dynamic keyword
var myPropertyValue = content.MyProperty; // Compiles just fine, retrieves the value of this at runtime (as long as it exists, of course)

特别是关于XML:,您可以尝试使用Anoop Madhusudanan's ElasticObject,这在dynamicXML之间进行转换时可能会非常有用。

特别是关于JSON:,您可以使用Json.NET执行以下操作:

dynamic content = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
var myPropertyValue = content.MyProperty;

最重要的是,你不会依赖Microsoft.AspNet.WebApi.Client包(从v4.0.30506.0开始,依赖于Json.NET)。缺点是您将无法将其用于XML。

希望这有帮助。

答案 1 :(得分:2)

HttpResponseMessage.Content视为动态,可以将直接直接视为动态,但使用正确的扩展方法将其内容读取为 ExpandoObject 即可。

我为此编写了一个行为测试,很明显是一个测试,但上下文与您的问题类似:

  1. 带有json内容的响应对象(我在测试中使用了json)
  2. 没有模型对象的动态分辨率
  3. 测试结构如下:

    1. 给出一个匿名对象
    2. 使用JsonMedia Formatter
    3. 创建包含此对象内容的HttpResponseMessage
    4. 然后可以使用ExpandoObject
    5. 以动态方式访问它

      测试先决条件是安装Microsoft.AspNet.WebApi.Client 所以,这是测试的代码

      public class RetrieveAnonymousTypeFromTheWebInCSharp 
          : BehaviorTest
      {
          private object _testModel;
          private HttpResponseMessage _message;
      
          protected override void Given()
          {
              _testModel = new
                  {
                      Id = 14,
                      MyProperty = "Test property value"
                  };
          }
      
          protected override void When()
          {
              _message = new HttpResponseMessage(HttpStatusCode.Accepted)
                             {
                                 Content =
                                     new ObjectContent(_testModel.GetType(),
                                                       _testModel,
                                                       new JsonMediaTypeFormatter
                                                           ())
                             };
          }
      
          [Test]
          public void Then()
          {
              //then properties could be retrieved back by dynamics
              dynamic content = _message.Content.ReadAsAsync<ExpandoObject>().Result;
              var propertyvalue = content.MyProperty;
              Assert.That(propertyvalue, Is.Not.Null.And.EqualTo("Test property value"));
          }
      }
      

      对于xml也可以做到这一点。