12

i have a class like

   [Serializable]
    public class MyClass
    {
        [XmlAttribute]
        public bool myBool { get; set; }
    }

But this serializes the value of the bool to false when the attribute is not present in the xml. When the attribute is not in the xml I want the property to be null.

So i tried this

[Serializable]
public class MyClass
{
    [XmlAttribute]
    public bool? myBool { get; set; }
}

But then the serializer errors

Type t = Type.GetType("Assembly.NameSpace.MyClass");
                XmlSerializer mySerializer = new XmlSerializer(t); //error "There was an error reflecting type"

Please give me a example of i can do this. I know there are some related questions on SO but nothing that shows how to overcome the reflection error with a nullable bool. Thanks.

Jules
  • 1,071
  • 2
  • 18
  • 37

4 Answers4

10

You need to use the "*Specified" field pattern to control this (see "Controlling Generated XML" on MSDN):

[Serializable]
public class MyClass
{
    [XmlAttribute]
    public bool myBool { get; set; }

    [XmlIgnore]
    public bool myBoolSpecified;
}

The logic now becomes:

  • If !myBoolSpecified, then myBool is logically null
  • Else use the true or false of myBool
Jon
  • 428,835
  • 81
  • 738
  • 806
  • @Aliostad: I appreciate the merits of your approach, but if the XML structure is not open to modification it will not work while this one will. – Jon Mar 30 '12 at 12:18
  • this looks great but doesnt seem to work. Is the '{}Specified' a magic name? do I need some logic in the getter? – Jules Mar 30 '12 at 12:22
  • @Jules: Yes, it's a magic name. Search for "The pattern is created in the form of propertyNameSpecified" on the linked page. If it doesn't work please show your current code. – Jon Mar 30 '12 at 12:24
  • 1
    I have a problem with this. Whilst it does leave out the attribute when deserialising it doesnt serialise the property to an attribute when the property has a value. I need the solution to work in both directions. – Jules Mar 30 '12 at 14:07
  • @Jules: I 'm not sure what you mean. What's the value of both the property and the field when you serialize? – Jon Mar 30 '12 at 17:05
  • I have a real problem with this as well. This is a major in the serializer. So, we can serialize nullable integers, but we can't serialize nullable bools? Madness. – Christian Findlay Jun 07 '18 at 09:26
3

Have a look at this for information regarding dealing with nullable fields and XML attributes. There is a similar question here too. Basically the serializer cannot handle an XML attribute field defined as nullable, but there is a work-around.

I.e 2 properties, one which contains the nullable (not XML stored), and the other which is used in the read/writing (XML attribute stored as a string). Perhaps this might be what you need?

private bool? _myBool;
[XmlIgnore]
public bool? MyBool
{
    get
    {
        return _myBool;
    }
    set
    {
        _myBool = value;
    }
}

[XmlAttribute("MyBool")]
public string MyBoolstring
{
    get
    {
        return MyBool.HasValue
        ? XmlConvert.ToString(MyBool.Value)
        : string.Empty;
    }
    set
    {
        MyBool =
        !string.IsNullOrEmpty(value)
        ? XmlConvert.ToBoolean(value)
        : (bool?)null;
    }
}
Community
  • 1
  • 1
Jeb
  • 3,689
  • 5
  • 28
  • 45
2

The problem is that a nullable type has to be defined as an element (which is default) and not Attribute.

Reason is when the value is null, it can be represented as <mybool xs:nil="true"/> as such cannot be represented as attribute.

Have a look at this snippet:

[Serializable]
public class MyClass
{
    // removed the attribute!!!
    public bool? myBool { get; set; }
}

And:

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
var stream = new MemoryStream();
serializer.Serialize(stream, new MyClass(){myBool = null});
Console.WriteLine(Encoding.UTF8.GetString(stream.ToArray()));

Output:

<?xml version="1.0"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.o
rg/2001/XMLSchema-instance">
  <myBool xsi:nil="true" /> <!-- NOTE HERE !!! -->
</MyClass>
Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • Thanks, but this is attribute in the xml I receive so I cant control that. Is there any way to have a nullable bool attribute? – Jules Mar 30 '12 at 12:21
1

You can use XmlElementAttribute.IsNullable:

[Serializable]
public class MyClass
{
    [XmlElement(IsNullable = true)]
    public bool? myBool { get; set; }
}
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185