使用DataContractSerializer反序列化XML

16

我有一个Web服务,它返回以下数据:

<?xml version=""1.0"" encoding=""UTF-8""?>
<RESPONSE>
    <KEY>12345</KEY>
    <PROPERTY>
        <PROPERTY_ADDRESS>
            <STREET_NUM>25</STREET_NUM>
            <STREET_ADDRESS>ELM ST</STREET_ADDRESS>
            <STREET_PREFIX/>
            <STREET_NAME>ELM</STREET_NAME>
            <STREET_TYPE>ST</STREET_TYPE>
            <STREET_SUFFIX/>
        </PROPERTY_ADDRESS>
    </PROPERTY>
</RESPONSE>

我有一个需要匹配的类结构:

[DataContract(Name="RESPONSE", Namespace="")]
public class Response
{
    [DataMember(Name="KEY")]
    public string Key { get; set; }

    [DataMember(Name = "PROPERTY")]
    public Property Property { get; set; }
}

[DataContract(Name="PROPERTY", Namespace="")]
public class Property
{
    [DataMember(Name="PROPERTY_ADDRESS")]
    public PropertyAddress Address { get; set; }
}


[DataContract(Name="PROPERTY_ADDRESS", Namespace="")]
public class PropertyAddress
{
    [DataMember(Name="STREET_NUM")]
    public string StreetNumber { get; set; }

    [DataMember(Name = "STREET_ADDRESS")]
    public string StreetAddress { get; set; }

    [DataMember(Name = "STREET_PREFIX")]
    public string StreetPrefix { get; set; }

    [DataMember(Name = "STREET_NAME")]
    public string StreetName { get; set; }

    [DataMember(Name = "STREET_TYPE")]
    public string StreetType { get; set; }

    [DataMember(Name = "STREET_SUFFIX")]
    public string StreetSuffix { get; set; }
}

我的反序列化代码如下:

[Test]
public void TestMapping()
{
    var serializer = new DataContractSerializer(typeof(Response));

    Response response = null;

    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(XmlData)))
    {
        response = (Response)serializer.ReadObject(ms);
    }

    //This works
    Assert.AreEqual("12345", response.Key);

    //This works
    Assert.AreEqual("25", response.Property.Address.StreetNumber);

    //This FAILS. StreetAddress is null
    Assert.AreEqual("ELM ST", response.Property.Address.StreetAddress);
}

就我而言,我无法弄清楚为什么StreetAddress失败了。肯定是我忽略了一些简单的东西。


1
您的XML语法不正确。 <PROPERTY_ADDRESS> 结束标签缺少 /。如果这正是您的服务返回的内容,那么一定会影响反序列化。 - SWalters
@SandraWalters:那是我问题中的一个笔误,而不是实际数据中的。 - Micah
1
我得到了相同的结果。街道地址有一个空值。 - Son_of_Sam
1
更奇怪的是,如果您改变xml的顺序(例如将STREET_ADDRESS移到顶部),它会神奇地正确反序列化该属性。 - Micah
可能是WCF DataContract DataMember order?的重复问题。 - chwarr
显示剩余7条评论
2个回答

26

DataContractSerializer期望事物按字母顺序排列。为使其正常工作,您需要为数据成员添加Order

[DataContract(Name = "PROPERTY_ADDRESS", Namespace = "")]
public class PropertyAddress
{
    [DataMember(Name = "STREET_NUM", Order=0)]
    public string StreetNumber { get; set; }

    [DataMember(Name = "STREET_ADDRESS", Order=1)]
    public string StreetAddress { get; set; }

    [DataMember(Name = "STREET_PREFIX", Order=2)]
    public string StreetPrefix { get; set; }

    [DataMember(Name = "STREET_NAME", Order=3)]
    public string StreetName { get; set; }

    [DataMember(Name = "STREET_TYPE", Order=4)]
    public string StreetType { get; set; }

    [DataMember(Name = "STREET_SUFFIX",Order=5)]
    public string StreetSuffix { get; set; }
}

22
我认为任何“性能”提升都被开发人员浪费在试图寻找、调试和修复这个愚蠢需求上的巨大时间所抵消了。 - Carl Onager
那么... 你如何禁用这种行为? - BrainSlugs83
2
这真的很令人沮丧,我刚刚花了3个小时才弄清楚那是问题所在。 - SecureTeam Software
2
@EranD。我也刚花了大约3个小时才最终发现这个问题...FML。微软还想知道为什么开发人员对他们的产品感到幻灭。 - crush
10
我想为你的回答准确性和实用性点个赞,但因其包含的残酷真相而要点个踩。;) - teedyay
显示剩余3条评论

7

您需要扩展数据合同以按元素顺序排序,因为DataContractSerializer默认情况下期望元素按字母顺序排列。但这在您的XML中并非如此。

以下是代码:

[DataContract(Name = "PROPERTY_ADDRESS", Namespace = "")]
public class PropertyAddress
{
    [DataMember(Name = "STREET_NUM", Order=1)]
    public string StreetNumber { get; set; }

    [DataMember(Name = "STREET_ADDRESS", Order=2)]
    public string StreetAddress { get; set; }

    [DataMember(Name = "STREET_PREFIX", Order=3)]
    public string StreetPrefix { get; set; }

    [DataMember(Name = "STREET_NAME", Order=4)]
    public string StreetName { get; set; }

    [DataMember(Name = "STREET_TYPE", Order=5)]
    public string StreetType { get; set; }

    [DataMember(Name = "STREET_SUFFIX", Order=6)]
    public string StreetSuffix { get; set; }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接