简体   繁体   English

在 XML 反序列化中将空字符串处理为 Null

[英]Handle Empty String as Null in XML Deserialization

I have the same problem with regard to this question .关于这个问题,我有同样的问题。 I am sending data back and forth with a SOAP-based API where the responses don't follow the standard quite right, specifically with null values.我使用基于 SOAP 的 API 来回发送数据,其中响应不完全符合标准,特别是 null 值。 For DateTime , the API will send back an empty string, like this:对于DateTime , API 将返回一个空字符串,如下所示:

<nextreview></nextreview>

Which causes the following error to occur on deserialization:这导致反序列化时发生以下错误:

The string '' is not a valid AllXsd value.字符串 '' 不是有效的 AllXsd 值。

So my thought was to create a custom Nullable type, NullableOrEmpty<T> , implementing IXMLSerializable that handles empty string by converting it to null.所以我的想法是创建一个自定义的 Nullable 类型NullableOrEmpty<T> ,实现IXMLSerializable通过将其转换为 null 来处理空字符串。 The problem is I only want to handle the exceptional case of an empty string.问题是我只想处理空字符串的例外情况。 Everything else I want to serialize and deserialize as normal, using the 'default' behavior.我想使用“默认”行为正常序列化和反序列化的所有其他内容。 How do I simulate the default behavior of serialization in my code below?如何在下面的代码中模拟序列化的默认行为?

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);
    }

}

When I say "THIS DOESN'T WORK", it specifically generates the following error message, probably because it's trying to consume something that isn't there:当我说“这不起作用”时,它专门生成以下错误消息,可能是因为它试图消耗不存在的东西:

There is an error in XML document (63, 6). XML 文档 (63, 6) 中存在错误。

<lastreview xmlns=''> was not expected. <lastreview xmlns=''>不是预期的。

Here is a snippet of XML at that spot.这是该位置的 XML 片段。 The error is caused by the value in birthdate , because I'm not consuming it correctly in the non-exceptional case where the value is actually given:该错误是由中的值引起的birthdate ,因为在实际给出值的非异常情况下我没有正确使用它:

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

Any thoughts or ideas are appreciated.任何想法或想法表示赞赏。 I can post more code samples if needed or test out suggestions.如果需要,我可以发布更多代码示例或测试建议。 Thanks!谢谢!

One thing you can do here, though it may be more of a pain is to implement the adapter pattern, where the object you populate from the xml result just has properties of type string, then write a converter method to populate your 'real' object checking for empty strings when the destination property is DateTime.您可以在这里做的一件事,虽然它可能更痛苦的是实现适配器模式,您从 xml 结果填充的 object 仅具有字符串类型的属性,然后编写一个转换器方法来填充您的“真实” ZA8CFDE6331CBD4B862AC1当目标属性为 DateTime 时检查空字符串。 It may be easier than implementing your own serializer.它可能比实现自己的序列化器更容易。

I am no longer using this class (I am requiring validations by the 3rd party instead), but I was actually able to get it to working by manually handling all the data types using the XmlConvert helpers:我不再使用这个 class (我需要由第 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM