11

我正在尝试从网络上检索一些数据。数据以 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)中的任何一种都可能吗?我该怎么做?

4

2 回答 2

23

编辑#2:

我在下面添加了一条关于使用出色的Json.NET库反序列化为dynamic对象的注释。


编辑#1:

感谢Hoghweed 的回答,我下面的回答现在更完整了。具体来说,我们需要HttpContent我们得到的转换HttpResponseMessage.ContentExpandoObject以使dynamic-ness 按预期工作:

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

但是,要获得ReadAsync<T>()扩展方法,您需要使用NuGetSystem.Net.Http.Formatting.dllMicrosoft.AspNet.WebApi.Client包中下载和安装(这里是“旧”Nuget 页面,其中提到它现在包含在上述包中)。


原答案:

因此,您不希望创建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'sElasticObjectdynamic ,这在和之间进行转换时可能非常有用XML,并且返回。

特别是关于 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。

希望这可以帮助。

于 2013-08-01T09:16:51.927 回答
3

HttpResponseMessage.Content将其作为动态读取是可能的,但不能直接将其作为动态访问,而是使用适当的扩展方法将其内容读取为ExpandoObject

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

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

测试结构如下:

  1. 给定一个匿名对象
  2. HttpResponseMessage使用 JsonMedia 格式化程序创建包含此对象的内容时
  3. 然后可以使用动态访问它ExpandoObject

测试先决条件是安装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 完成。

于 2013-08-01T13:33:23.303 回答