永发信息网

Serializer序列化对象时,如何去掉空元素

答案:1  悬赏:10  手机版
解决时间 2021-03-12 22:12
Serializer序列化对象时,如何去掉空元素
最佳答案
使用XmlSerializer可以方便的将对象序列化为xml,实现应用之间的数据交互。但是XmlSerializer却不能很好地序列化类型中的可为null的字段。
例如,有如下定义的类Person:
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
public string FirstName { get; set; }

public string LastName { get; set; }

public int? Age { get; set; }
}
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
public string FirstName { get; set; }

public string LastName { get; set; }

public int? Age { get; set; }
}

其中的Age属性为Nullable int类型。
我们的实例化代码如下所示:
var person = new Person
{
FirstName = "First",
};
person.OutputXml(Console.Out);
var person = new Person
{
FirstName = "First",
};
person.OutputXml(Console.Out);

其中方法OutputXml为扩展方法,使用XmlSerializer来序列化对象,具体定义为:
public static void OutputXml(this T dto, TextWriter textWriter)
{
var xmlTypeMapping = typeof(T);
var serializer = new XmlSerializer(xmlTypeMapping);
var xmlns = new XmlSerializerNamespaces();
xmlns.Add(string.Empty, string.Empty);
using (var writer = new XmlTextWriter(textWriter) { Formatting = Formatting.Indented })
{
serializer.Serialize(writer, dto, xmlns);
}
}
public static void OutputXml(this T dto, TextWriter textWriter)
{
var xmlTypeMapping = typeof(T);
var serializer = new XmlSerializer(xmlTypeMapping);
var xmlns = new XmlSerializerNamespaces();
xmlns.Add(string.Empty, string.Empty);
using (var writer = new XmlTextWriter(textWriter) { Formatting = Formatting.Indented })
{
serializer.Serialize(writer, dto, xmlns);
}
}

使用上述方法序列化对象person,得到的结果为:

注意到虽然Age属性为空,却仍然被序列化成 了古怪的xml,这往往不是所期望的结果。事实上同为空的LastName属性的序列化正是大多数情况下我们所期望的行为——忽略为空的属性。
另一方面,如果试图序列化类属性为xml 属性(而非xml元素),则甚至不能工作。例如如果我们将Person类的定义修改成如下形式以便序列化为xml属性:
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
[XmlAttribute]
public string FirstName { get; set; }

[XmlAttribute]
public string LastName { get; set; }

[XmlAttribute]
public int? Age { get; set; }
}
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
[XmlAttribute]
public string FirstName { get; set; }

[XmlAttribute]
public string LastName { get; set; }

[XmlAttribute]
public int? Age { get; set; }
}

Xmlserializer甚至无法正常序列化上面同样的person对象并抛出如下“XmlAttribute/XmlText cannot be used to encode complex types”的错误:

如何解决上述的2个问题呢?
1. 序列化可为null属性输出为XmlElement
为了在序列化可空属性的时候忽略空值的古怪输出,我们可以在Person类中定义一个返回bool的特殊方法 ShouldSerializeAge,并在其中实现定义我们的序列化规则:
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
public string FirstName { get; set; }

public string LastName { get; set; }

public int? Age { get; set; }

public bool ShouldSerializeAge()
{
return Age.HasValue;
}
}
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
public string FirstName { get; set; }

public string LastName { get; set; }

public int? Age { get; set; }

public bool ShouldSerializeAge()
{
return Age.HasValue;
}
}

在这里我们定义序列化规则为:序列化非空Age。注意该方法的名字一定是以ShouldSerialize开头并连接上需要自定义规则的属性名 称。这样序列化出来的person对象为:

空的Age和空的LastName一样在序列化时被忽略了输出。正是我们期望的结果!
2. 序列化可为null的属性输出为XmlAttribute
由于可空属性无法被直接序列化为XmlAttribute,我们需要采用间接的办法——定义间接属性。此时我们可以如下定义Person类:
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
[XmlAttribute]
public string FirstName { get; set; }

[XmlAttribute]
public string LastName { get; set; }

[XmlIgnore] // (4)
public int? Age { get; set; }

[XmlAttribute(AttributeName = "Age")] // (1)
public string AgeValue
{
get
{
// (2)
return Age.HasValue ? Age.Value.ToString() : null;
}
set
{
int result;
// (3)
Age = int.TryParse(value, out result) ? result : (int?) null;
}
}
}
[Serializable]
[XmlRoot(ElementName = "Person")]
public class Person
{
[XmlAttribute]
public string FirstName { get; set; }

[XmlAttribute]
public string LastName { get; set; }

[XmlIgnore] // (4)
public int? Age { get; set; }

[XmlAttribute(AttributeName = "Age")] // (1)
public string AgeValue
{
get
{
// (2)
return Age.HasValue ? Age.Value.ToString() : null;
}
set
{
int result;
// (3)
Age = int.TryParse(value, out result) ? result : (int?) null;
}
}
}
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
发展路/密三路(路口)在什么地方啊,我要过去
32渔夫的故事渔夫是一个( )的人魔鬼是一个( )
怎么把歌曲原唱去掉
我想买招财猫香烟。
电脑键盘打字v打出来是>怎么办
占全清真餐厅羊羔肉炒烩肉大盘鸡地址在什么地
美孚唯是盾金霸王15W-40,18L机油是全合成机
依据《规划环境影响评价技术导则总纲》(HJ13
大功率激光笔可以治远光狗吗
捷达,爱丽舍,手动挡的怎么选?
武汉大学信息学部国际软件学院(西门)在哪里啊
右图中,甲表示植物的淀粉酶与人的淀粉酶活性
捕将铠甲图片和武器名叫什么名字
谁知道TPEE 6465的物性表
横幅 图片滚动的问题。设置了js,但是图片没
推荐资讯
汇东综合批零商店地址有知道的么?有点事想过
亮亮综合门市部我想知道这个在什么地方
哪个网站起名字最好
高中英语语法填空,if you struggle against
请大家帮我看看这块海洋玉髓值多少钱?
鄱湖国际珠贝商务中心地址有知道的么?有点事
六指能割吗?拜托各位大神
衡水通力汽车销售服务有限公司我想知道这个在
把厂房上下分隔成两层可以么
苹果被偷了刷机了id还可以用吗
本人教师一枚,工作三年已经有一教师资格证,
邪气鞍座共享吗
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?