使用XmlSerializer可以方便的将对象序列化为xml,实现应用之间的数据交互。但是XmlSerializer却不能很好地序列化类型中的可为null的字段。
例如,有如下定义的类Person:

C#代码 
  1. [Serializable]
  2. [XmlRoot(ElementName = "Person")]
  3. public class Person
  4. {
  5. public string FirstName { get; set; }
  6. public string LastName { get; set; }
  7. public int? Age { get; set; }
  8. }
    [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类型。
我们的实例化代码如下所示:

C#代码 
  1. var person = new Person
  2. {
  3. FirstName = "First",
  4. };
  5. person.OutputXml(Console.Out);
            var person = new Person{FirstName = "First",};person.OutputXml(Console.Out);

其中方法OutputXml为扩展方法,使用XmlSerializer来序列化对象,具体定义为:

C#代码 
  1. public static void OutputXml<T>(this T dto, TextWriter textWriter)
  2. {
  3. var xmlTypeMapping = typeof(T);
  4. var serializer = new XmlSerializer(xmlTypeMapping);
  5. var xmlns = new XmlSerializerNamespaces();
  6. xmlns.Add(string.Empty, string.Empty);
  7. using (var writer = new XmlTextWriter(textWriter) { Formatting = Formatting.Indented })
  8. {
  9. serializer.Serialize(writer, dto, xmlns);
  10. }
  11. }
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属性:

C#代码 
  1. [Serializable]
  2. [XmlRoot(ElementName = "Person")]
  3. public class Person
  4. {
  5. [XmlAttribute]
  6. public string FirstName { get; set; }
  7. [XmlAttribute]
  8. public string LastName { get; set; }
  9. [XmlAttribute]
  10. public int? Age { get; set; }
  11. }
    [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,并在其中实现定义我们的序列化规则:

C#代码 
  1. [Serializable]
  2. [XmlRoot(ElementName = "Person")]
  3. public class Person
  4. {
  5. public string FirstName { get; set; }
  6. public string LastName { get; set; }
  7. public int? Age { get; set; }
  8. public bool ShouldSerializeAge()
  9. {
  10. return Age.HasValue;
  11. }
  12. }
    [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类:

C#代码 
  1. [Serializable]
  2. [XmlRoot(ElementName = "Person")]
  3. public class Person
  4. {
  5. [XmlAttribute]
  6. public string FirstName { get; set; }
  7. [XmlAttribute]
  8. public string LastName { get; set; }
  9. [XmlIgnore]   // (4)
  10. public int? Age { get; set; }
  11. [XmlAttribute(AttributeName = "Age")]  // (1)
  12. public string AgeValue
  13. {
  14. get
  15. {
  16. // (2)
  17. return Age.HasValue ? Age.Value.ToString() : null;
  18. }
  19. set
  20. {
  21. int result;
  22. // (3)
  23. Age = int.TryParse(value, out result) ? result : (int?) null;
  24. }
  25. }
  26. }
    [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;}}}

注意类中注释的部分:

  1. 为原可空属性定义一个“虚拟”的属性,该属性可为任意名称任意类型(示例里定义的为string类型的AgeValue),但注意要将该属性的序 列化名称置为原可空属性Age。
  2. 在get方法里根据Age是否为空将其转化为AgeValue。
  3. 在set方法里将输入的value转化为合适的值赋给可空属性Age。
  4. 将原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)相关推荐

  1. 项目中序列化时,去除属性为null的key

    项目中对象属性中的字段有很多时,每次查询需要的属性都不同,但是还是返回null,过滤掉为空的方法 1.@JsonIgnore标签 此注解用于方法或者属性上(最好就是用在属性上),作用就是在对象做序列化 ...

  2. java对象json序列化时忽略值为null的属性

    当一个对象里有些属性值为null 的不想参与json序列化时,可以添加如下注解复制代码 import com.fasterxml.jackson.annotation.JsonInclude; imp ...

  3. XML序列化以及新增节点XMLHelper

    介绍利用XMLHelper类实现XML的新建以及反序列化类的操作,XMLHelper见最底部 1.XML新增 document = XmlHelper.CreateXmlDocument(" ...

  4. C#里XML(JSON)序列化时,自动隐藏值为Null的成员的输出

    原文:C#里XML(JSON)序列化时,自动隐藏值为Null的成员的输出 从StackOverflow里找到的答案.发现对最新的Newtownsoft的JSON序列化也同样适用. https://st ...

  5. html 表格隐藏 显示出来了,如何在html页面打开时隐藏表格

    Hallo there 我有一些javascript代码,当我的鼠标移过链接时可以看到一个表格,当鼠标移出时隐藏. 我遇到的问题是在页面打开时让表格"隐藏". 我怎么能做到这一点. ...

  6. 对消息 的正文进行序列化时出错:“生成 XML 文档时出错。”

    c# 执行存储过程时报错:对消息  的正文进行序列化时出错:"生成 XML 文档时出错." 原因是在执行存储过程时传递的里面包含有表,但是我没有给表命名. 解决方法是给声明的表命名 ...

  7. c语言xml序列化,C# XML和实体类之间相互转换(序列化和反序列化)

    我们需要在XML与实体类,DataTable,List之间进行转换,下面是XmlUtil类,该类来自网络并稍加修改. using System; using System.Collections.Ge ...

  8. 简单介绍实体类或对象序列化时,忽略为空属性的操作

    这篇文章主要介绍了实体类或对象序列化时,忽略为空属性的操作,具有很好的参考价值,希望对大家有所帮助.如有错误或未考虑完全的地方,望不吝赐教 第一种,在配置文件配置 在application.xml直接 ...

  9. [C#][Newtonsoft.Json] Newtonsoft.Json 序列化时的一些其它用法

    Newtonsoft.Json 序列化时的一些其它用法 在进行序列化时我们一般会选择使用匿名类型 new { },或者添加一个新类(包含想输出的所有字段).但不可避免的会出现以下情形:如属性值隐藏(敏 ...

  10. 【Hibernate】Hibrenate POJO 类在序列化时遇到的问题

    2019独角兽企业重金招聘Python工程师标准>>> 假设某 POJO 有属性如下: private Set<User> users = new HashSet< ...

最新文章

  1. mysql Tablespace exists解决
  2. 如何用TXT文档数据批量生成条形码
  3. 服务器客户端回射程序-自己设计包的结构
  4. 数据结构【高精度专题】
  5. 伟大公司为什么需要技术型领导?
  6. Apache从入门到精通
  7. RiskSense Spotlight:全球知名开源软件漏洞分析报告
  8. 我的Maven POM配置
  9. (转)JAVA实现Windows拨号、IP切换
  10. 会员分享几个平时看榜单常去的网站
  11. “华为杯”第17届中国研究生数学建模竞赛B题二等奖论文
  12. ISO安装CoreOS
  13. BP神经网络详解+原理
  14. 外汇投资风险在哪里.
  15. 前端开发工程师原生html进阶指南
  16. 海豚php完全开发手册,ThinkPHP2.1完全开发手册
  17. 大学计算机组装作业台式,组装一部单机作业基本型计算机的50步骤
  18. supserset权限管理
  19. uniapp 获取 iphone x 底部黑线高度_你知道 iPhone 可以称重吗?附快捷指令版,更方便...
  20. Machine Learning Basics(1)

热门文章

  1. mysql事件【定时器】
  2. Java多线程系列---“基础篇”08之 join()
  3. redis命令_INCR
  4. Java_基础—readLine()和newLine()方法
  5. Flutter从零到∞学习笔记
  6. Beta版本冲刺(四)
  7. Android Studio使用tips
  8. UITableViewCell delete button 上有其它覆盖层
  9. 关于防止sql注入的几种手段
  10. vue 如何读取编译携带的参数