【问题标题】:Deserialize XML Rest WebApi Call?反序列化 XML Rest WebApi 调用?
【发布时间】:2015-02-11 20:12:50
【问题描述】:

我一直在关注一些在线示例,但由于某种原因,我无法成功反序列化以下 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <postcode>BD1 1LT</postcode>
    <geo>
        <lat>53.793063240118215</lat>
        <lng>-1.7540318423563699</lng>
        <easting>416300.0</easting>
        <northing>433000.0</northing>
        <geohash>http://geohash.org/gcwf00dz21g1</geohash>
    </geo>
    <administrative>
        <council>
            <title>Bradford</title>
            <uri>http://statistics.data.gov.uk/id/statistical-geography/E08000032</uri>
            <code>E08000032</code>
        </council>
        <ward>
            <title>City</title>
            <uri>http://statistics.data.gov.uk/id/statistical-geography/E05001347</uri>
            <code>E05001347</code>
        </ward>
        <constituency>
            <title>Bradford West</title>
            <uri>http://statistics.data.gov.uk/id/statistical-geography/E14000589</uri>
            <code>E14000589</code>
        </constituency>
    </administrative>
</result>

我尝试了各种组合:

[DataContract(Name = "result", Namespace = "")]
public class Result
{
    [DataMember(Name = "postcode")]
    public string Postcode { get; set; }
    [DataMember(Name = "geo")]
    public Geo Geo { get; set; } 
}

[DataContract(Name = "geo")]
public class Geo
{
    [DataMember(Name = "lat")]
    public string Lat { get; set; } 
}

但我能得到的只是邮政编码,没有别的。 以上 是我所拥有的 工作空间

以下是我根据一些示例汇总的内容:

    [Test]
    public void TestRestCall()
    {
        var url = "http://uk-postcodes.com/postcode/";
        var urlParameters = "bd11lt.xml";
        var client = new HttpClient();
        client.BaseAddress = new Uri(url);

        // Add an Accept header for JSON format.
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

        // List data response.
        HttpResponseMessage response = client.GetAsync(urlParameters).Result;  // Blocking call!
        if (response.IsSuccessStatusCode)
        {
            // Parse the response body. Blocking!
            var dataObjects = response.Content.ReadAsAsync<Result>().Result;
            //Console.WriteLine("{0}", dataObjects.Geo.);
        }
        else
        {
            Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
        } 
    }

更新:

Geo 属性为空,这是我所能得到的。

【问题讨论】:

    标签: c# xml asp.net-web-api deserialization


    【解决方案1】:

    我看到了两个问题。一个是排序,另一个是命名空间。

    您需要指定所有属性和对象的顺序,但还需要指定所有属性和对象的命名空间。

        [DataContract(Name = "result", Namespace = "")]
        public class Result
        {
            [DataMember(Name = "postcode", Order = 1)]
            public string Postcode { get; set; }
    
            [DataMember(Name = "geo", Order = 2)]
            public Geo Geo { get; set; }
        }
    

    同样,在您的 GEO 对象上,您必须同时指定两者,以便映射在 HttpClient 上工作。

        [DataContract(Name = "geo", Namespace = "")]
        public class Geo
        {
            [DataMember(Name = "lat", Order = 1)]
            public string Lat { get; set; }
        }
    

    希望对您有所帮助。

    【讨论】:

    • Geo 的命名空间在这里无关紧要,因为它不是文档的根元素,lat 的排序也不重要(至少,现在还没有),因为它是他唯一的元素反序列化。
    • 如果你把它们拿出来它不会工作......试试......至少需要确定命名空间,因为xml的格式化方式......
    • 好吧,我在 NS 中添加了,我得到:第 1 行位置 9 中的错误。期望来自命名空间 'schemas.datacontract.org/2004/07/RiskChecker.Lib' 的元素 'result'.. 遇到名称为 'result'、命名空间的 'Element' ''。这是有道理的,因为元素是从没有命名空间的 WebService 接收的。所以命名空间可以省略。
    • 我自己试过了,但在 GEO 上缺少命名空间肯定失败了
    • 我的最后一条评论是 derped,我没有意识到我也添加了空的命名空间。
    【解决方案2】:

    一个排序的东西,但它是一个你可以用你的Result定义来解决的问题。 DataContractSerializer,除非另有说明,否则期望元素按字母顺序排列,而不是类中定义的顺序。但是,您可以使用DataMemberOrder 属性来明确告诉它期望和发出元素的顺序。

    Result 的定义更改为

    [DataContract(Name = "result", Namespace = "")]
    public class Result
    {
        [DataMember(Name = "postcode", Order = 1)]
        public string Postcode { get; set; }
    
        [DataMember(Name = "geo", Order = 2)]
        public Geo Geo { get; set; }
    }
    

    应该可以解决您的问题。您可以参考MSDN 以获得更完整的数据合约中排序语义的描述。

    根据@LouieBacaj 的回答,您还需要将空命名空间添加到您的Geo 类中以正确反序列化嵌套元素:

    [DataContract(Name = "geo", Namespace = "")]
    public class Geo
    {
        [DataMember(Name = "lat")]
        public string Lat { get; set; }
    }
    

    【讨论】:

    • 看到的是,它是一个公共 API,所以我不知道明确的顺序,所以在代码中定义一个纯粹是猜测工作。这样做时,属性被简单地设置为 null。
    • 公共 API 更好 发布架构定义。
    【解决方案3】:

    public string Geo 应该是public Geo Geo,不是吗?

    【讨论】:

    • 另外 - 我认为带有名称的数据合同会越过结果中的 Geo。这种东西的捷径是使用一个工具,从 XML 生成 XSD,然后为您从 XSD 生成类。 XSD.exe 会为您执行此操作。
    • 谢谢,做了一些改变,但现在它没有抛出异常,但现在 Geo 为 Null。我希望这不是订购的东西。由于它是一个公开免费使用的 API,所以希望有人知道如何让它正常工作。
    • 我无权访问该网站,但我将其加载到内存流中并通过DataContractSerializer 传递它并正确反序列化。所以也许这是在HttpClient中配置解串器的方式?
    猜你喜欢
    • 2013-09-21
    • 2014-04-26
    • 2023-03-11
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2020-10-16
    相关资源
    最近更新 更多