XmlSerializer property converter

2020-02-01 03:30发布

Suppose we have a class which can be serialized/deserialized by XmlSerializer. It would be like so:

[XmlRoot("ObjectSummary")]
public class Summary
{
     public string Name {get;set;}
     public string IsValid {get;set;}
}

We have an xml which will be like so:

<ObjectSummary>
   <Name>some name</Name>
   <IsValid>Y</IsValid>
<ObjectSummary>

Using of boolean property IsValid instead of string property is much better decision, but in this case we need to add some additional logic to convert data from string to bool.

The simple and direct way to solve this problem is to use additional property and put some conversion logic into the IsValid getter.

Can anyone suggest a better decision? To use a type converter in attributes somehow or something similar?

3条回答
够拽才男人
2楼-- · 2020-02-01 04:13

Treat the node as a custom type:

[XmlRoot("ObjectSummary")]
public class Summary
{
    public string Name {get;set;}
    public BoolYN IsValid {get;set;}
}

Then implement IXmlSerializable on the custom type:

public class BoolYN : IXmlSerializable
{
    public bool Value { get; set }

    #region IXmlSerializable members

    public System.Xml.Schema.XmlSchema GetSchema() {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader) {
        string str = reader.ReadString();
        reader.ReadEndElement();

        switch (str) {
            case "Y":
                this.Value = true;
                break;
            case "N":
                this.Value = false;
                break;
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer) {
        string str = this.Value ? "Y" : "N";

        writer.WriteString(str);
        writer.WriteEndElement();
    }

    #endregion
}

You can even make that custom class a struct instead, and provide implicit conversions between it and bool to make it even more "transparent".

查看更多
一纸荒年 Trace。
3楼-- · 2020-02-01 04:26

The way I do it - which is suboptimal but have not found a better way - is to define two properties:

[XmlRoot("ObjectSummary")]
public class Summary
{
     public string Name {get;set;}
     [XmlIgnore]
     public bool IsValid {get;set;}
     [XmlElement("IsValid")]
     public string IsValidXml {get{ ...};set{...};}

}

Replace ... with the simple code to read and write the IsValid value to Y and N and read from it.

查看更多
何必那么认真
4楼-- · 2020-02-01 04:35
using Newtonsoft.Json;

[XmlRoot("ObjectSummary")]
public class Summary
{
     public string Name {get;set;}
     public string IsValid {get;set;}
}


 //pass objectr of Summary class you want to convert to XML
 var json = JsonConvert.SerializeObject(obj);
 XNode node = JsonConvert.DeserializeXNode(json, "ObjectSummary");

If you have more than one object, put it inside a list and Serialize List.

                dynamic obj = new ExpandoObject();
                obj.data = listOfObjects;
                var json = JsonConvert.SerializeObject(obj);
                XNode node = JsonConvert.DeserializeXNode(json, "ObjectSummary");
查看更多
登录 后发表回答