【问题标题】:Handle Empty String as Null in XML Deserialization在 XML 反序列化中将空字符串处理为 Null
【发布时间】:2011-05-24 21:55:07
【问题描述】:

我对@9​​87654321@ 有同样的问题。我正在使用基于 SOAP 的 API 来回发送数据,其中响应不完全正确地遵循标准,特别是使用空值。对于DateTime,API 将返回一个空字符串,如下所示:

<nextreview></nextreview>

导致反序列化时出现以下错误:

字符串 '' 不是有效的 AllXsd 值。

所以我的想法是创建一个自定义的 Nullable 类型 NullableOrEmpty&lt;T&gt;,实现 IXMLSerializable 通过将空字符串转换为 null 来处理空字符串。问题是我只想处理空字符串的例外情况。我想使用“默认”行为正常序列化和反序列化的所有其他内容。如何在下面的代码中模拟序列化的默认行为?

public class NullableOrEmpty<T> : IXmlSerializable
    where T : struct
{
    public T? NullableValue { get; set; }
    public T Value { get { return this.NullableValue.Value; } }
    public bool HasValue { get { return this.NullableValue.HasValue; } }

    ...

    public void ReadXml(XmlReader reader)
    {
        string xml = reader.ReadElementContentAsString();
        if (string.IsNullOrEmpty(xml))
        {
            this.NullableValue = null;
        }
        else
        {
            //THIS SHOULD DO THE DEFAULT. THIS DOESN'T WORK.  WHAT DO I DO??
            //this.NullableValue = (T?)new XmlSerializer(typeof(T?)).Deserialize(reader);
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        //THIS SHOULD DO THE DEFAULT.  THIS DOESN'T WORK. WHAT DO I DO??
        //new XmlSerializer(typeof(T?)).Serialize(writer, this.NullableValue);
    }

}

当我说“这不起作用”时,它专门生成以下错误消息,可能是因为它试图消耗不存在的东西:

XML 文档中存在错误(63, 6).

&lt;lastreview xmlns=''&gt; 不是 预计。

这里是那个位置的 XML 的 sn-p。该错误是由birthdate 中的值引起的,因为在实际给出该值的非异常情况下我没有正确使用它:

<udf4></udf4>
<udf3></udf3>
<birthdate>1978-05-24Z</birthdate>
<lastreview></lastreview>
<fulltime>1</fulltime>

感谢任何想法或想法。如果需要,我可以发布更多代码示例或测试建议。谢谢!

【问题讨论】:

  • 您不能使用相同的XmlReader。您已经阅读过想要再次阅读的内容。

标签: .net xml serialization null


【解决方案1】:

你可以在这里做的一件事,虽然它可能更痛苦的是实现适配器模式,你从 xml 结果填充的对象只有字符串类型的属性,然后编写一个转换器方法来填充你的 '当目标属性为 DateTime 时,真正的对象检查空字符串。这可能比实现自己的序列化程序更容易。

【讨论】:

  • 感谢您的意见。当它只影响 100 个属性中的大约 5 个时,我想避免添加一堆逻辑。我已经在这里看到了 shim 属性的想法:stackoverflow.com/questions/838246/…,这就是我最终可能会使用的。
  • 您的链接看起来是一个很好的解决方案。易于阅读,易于维护。
【解决方案2】:

我不再使用此类(我需要由第 3 方进行验证),但实际上我能够通过使用 XmlConvert 帮助程序手动处理所有数据类型来使其正常工作:

public void ReadXml(XmlReader reader)
{
    string xml = reader.ReadElementContentAsString();
    if (string.IsNullOrEmpty(xml))
    {
        this.NullableValue = null;
    }
    else
    {
        if (this.NullableValue is bool)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToBoolean(xml), typeof(T?));
        else if (this.NullableValue is byte)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToByte(xml), typeof(T?));
        else if (this.NullableValue is char)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToChar(xml), typeof(T?));
        else if (this.NullableValue is DateTime)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDateTime(xml), typeof(T?));
        else if (this.NullableValue is decimal)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDecimal(xml), typeof(T?));
        else if (this.NullableValue is double)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDouble(xml), typeof(T?));
        else if (this.NullableValue is Guid)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToGuid(xml), typeof(T?));
        else if (this.NullableValue is short)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt16(xml), typeof(T?));
        else if (this.NullableValue is int)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt32(xml), typeof(T?));
        else if (this.NullableValue is long)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt64(xml), typeof(T?));
        else if (this.NullableValue is float)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToSingle(xml), typeof(T?));
    }
}

public void WriteXml(XmlWriter writer)
{
    new XmlSerializer(typeof(T?)).Serialize(writer, this.NullableValue);
}

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 2013-12-04
    • 2014-10-15
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多