开发者

Handle Empty String as Null in XML Deserialization

开发者 https://www.devze.com 2023-03-07 23:46 出处:网络
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.Fo

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. For DateTime, the API will send back an empty string, like this:

<nextreview></nextreview>

Which causes the following error to occur on deserialization:

The string '' is not a valid AllXsd value.

So my thought was to create a custom Nullable type, NullableOrEmpty<T>, implementing IXMLSerializable that handles empty string by converting it to 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).

<lastreview xmlns=''> was not expected.

Here is a snippet of XML at that spot. 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:

<udf4></udf4>
<udf3></udf3>
<birthdate>1978-05-24Z</birthdate>
<lastreview></lastreview>
<fulltim开发者_如何学Ce>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. 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:

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

精彩评论

暂无评论...
验证码 换一张
取 消