如何在XML序列化时隐藏可为null的的字段(XmlElement和XmlAttribute)
使用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<T>(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<T>(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;}}}
注意类中注释的部分:
- 为原可空属性定义一个“虚拟”的属性,该属性可为任意名称任意类型(示例里定义的为string类型的AgeValue),但注意要将该属性的序 列化名称置为原可空属性Age。
- 在get方法里根据Age是否为空将其转化为AgeValue。
- 在set方法里将输入的value转化为合适的值赋给可空属性Age。
- 将原Age属性标记为XmlIgnore,使XmlSerializer在序列化时忽略序列化该属性。
使用上述方法,我们可以将Age序列化为XmlAttribute了,虽然实际上我们是“骗”了XmlSerializer并使用另一个属性作为 Age属性的值。
因此,当person对象中的Age为空时,我们得到如下的xml结果:
而当person对象中的Age不为空时,我们也可以正常的用XmlAttribute来表示Age的值了。
转载于:https://www.cnblogs.com/techmango/archive/2012/01/26/2329646.html
如何在XML序列化时隐藏可为null的的字段(XmlElement和XmlAttribute)相关推荐
- 项目中序列化时,去除属性为null的key
项目中对象属性中的字段有很多时,每次查询需要的属性都不同,但是还是返回null,过滤掉为空的方法 1.@JsonIgnore标签 此注解用于方法或者属性上(最好就是用在属性上),作用就是在对象做序列化 ...
- java对象json序列化时忽略值为null的属性
当一个对象里有些属性值为null 的不想参与json序列化时,可以添加如下注解复制代码 import com.fasterxml.jackson.annotation.JsonInclude; imp ...
- XML序列化以及新增节点XMLHelper
介绍利用XMLHelper类实现XML的新建以及反序列化类的操作,XMLHelper见最底部 1.XML新增 document = XmlHelper.CreateXmlDocument(" ...
- C#里XML(JSON)序列化时,自动隐藏值为Null的成员的输出
原文:C#里XML(JSON)序列化时,自动隐藏值为Null的成员的输出 从StackOverflow里找到的答案.发现对最新的Newtownsoft的JSON序列化也同样适用. https://st ...
- html 表格隐藏 显示出来了,如何在html页面打开时隐藏表格
Hallo there 我有一些javascript代码,当我的鼠标移过链接时可以看到一个表格,当鼠标移出时隐藏. 我遇到的问题是在页面打开时让表格"隐藏". 我怎么能做到这一点. ...
- 对消息 的正文进行序列化时出错:“生成 XML 文档时出错。”
c# 执行存储过程时报错:对消息 的正文进行序列化时出错:"生成 XML 文档时出错." 原因是在执行存储过程时传递的里面包含有表,但是我没有给表命名. 解决方法是给声明的表命名 ...
- c语言xml序列化,C# XML和实体类之间相互转换(序列化和反序列化)
我们需要在XML与实体类,DataTable,List之间进行转换,下面是XmlUtil类,该类来自网络并稍加修改. using System; using System.Collections.Ge ...
- 简单介绍实体类或对象序列化时,忽略为空属性的操作
这篇文章主要介绍了实体类或对象序列化时,忽略为空属性的操作,具有很好的参考价值,希望对大家有所帮助.如有错误或未考虑完全的地方,望不吝赐教 第一种,在配置文件配置 在application.xml直接 ...
- [C#][Newtonsoft.Json] Newtonsoft.Json 序列化时的一些其它用法
Newtonsoft.Json 序列化时的一些其它用法 在进行序列化时我们一般会选择使用匿名类型 new { },或者添加一个新类(包含想输出的所有字段).但不可避免的会出现以下情形:如属性值隐藏(敏 ...
- 【Hibernate】Hibrenate POJO 类在序列化时遇到的问题
2019独角兽企业重金招聘Python工程师标准>>> 假设某 POJO 有属性如下: private Set<User> users = new HashSet< ...
最新文章
- mysql Tablespace exists解决
- 如何用TXT文档数据批量生成条形码
- 服务器客户端回射程序-自己设计包的结构
- 数据结构【高精度专题】
- 伟大公司为什么需要技术型领导?
- Apache从入门到精通
- RiskSense Spotlight:全球知名开源软件漏洞分析报告
- 我的Maven POM配置
- (转)JAVA实现Windows拨号、IP切换
- 会员分享几个平时看榜单常去的网站
- “华为杯”第17届中国研究生数学建模竞赛B题二等奖论文
- ISO安装CoreOS
- BP神经网络详解+原理
- 外汇投资风险在哪里.
- 前端开发工程师原生html进阶指南
- 海豚php完全开发手册,ThinkPHP2.1完全开发手册
- 大学计算机组装作业台式,组装一部单机作业基本型计算机的50步骤
- supserset权限管理
- uniapp 获取 iphone x 底部黑线高度_你知道 iPhone 可以称重吗?附快捷指令版,更方便...
- Machine Learning Basics(1)