如果它为空或为空,如何从序列化中忽略可为空的属性?
Posted
技术标签:
【中文标题】如果它为空或为空,如何从序列化中忽略可为空的属性?【英文标题】:How to ignore a nullable property from serialization if it is null or empty? 【发布时间】:2013-04-16 20:36:11 【问题描述】:我有一个用于 Xml 序列化的类。
在其中我有一个可以为空的属性,用 XmlAttribute 装饰:
[XmlAttribute("lastUpdated")]
public DateTime? LastUpdated get; set;
如果属性为空或为空,如何从序列化中忽略该属性?
我已经尝试了以下方法,但是当有值时它不会序列化(总是忽略):
[XmlIgnore]
public DateTime? LastUpdatedValue get; set;
[XmlAttribute("lastUpdated")]
public DateTime LastUpdated get; set;
public bool ShouldSerializeLastUpdated()
return LastUpdatedValue.HasValue;
【问题讨论】:
你看过这个***.com/questions/244953/… 您希望 XML 是什么样子?在这种情况下,如果属性为 null,您将获得<lastUpdated xsi:nil="true"/>
;您可以对 xml 进行后处理(更容易),也可以编写一个 XmlWriter 类(更难,性能更好)。还有其他一些选项既困难又使您的代码膨胀。
不,如果 xmlattribute 为空,我只想忽略它。但是日期时间?不可序列化。怎么换?
【参考方案1】:
XmlSerialization 不直接支持 Nullable。
如果你想使用一个可以为空的属性,你必须使用一个不可为空的属性,并添加一个与属性同名的布尔属性,后缀为“指定”,指定何时该属性必须是可序列化的。
你的例子:
private DateTime? _lastUpdated;
[XmlAttribute("lastUpdated")]
public DateTime LastUpdated
get
return (DateTime)_lastUpdated;
set
_lastUpdated = value;
public bool LastUpdatedSpecified
get
return _lastUpdated.HasValue;
【讨论】:
谢谢,但问题是我无法再使用 XmlSerializer 对其进行序列化。我收到了这个错误:+ InnerException “有一个错误反映属性'LastUpdated'。” System.Exception System.InvalidOperationException 对不起,我太快了,我更正并编辑了我的代码。你可以试试这个吗? @TheLight 你能接受我的回答,比如最佳回复吗? 如果_lastUpdated
没有值,return (DateTime)_lastUpdated;
将抛出InvalidOperationException
。
LastUpdatedSpecified 用在哪里?【参考方案2】:
我知道这个话题很老了。这是我带来的解决方案。封装类型的类,并隐式转换为类型。序列化时,成员变量可以用IsNullable = false标记,不会出现编译器错误,并且在为null时阻止它被序列化。
public class Optional<T> where T : struct, IComparable
public Optional(T valueObject)
Value = valueObject;
public Optional()
[XmlText]
public T Value get; set;
public static implicit operator T(Optional<T> objectToCast)
return objectToCast.Value;
public static implicit operator Optional<T>(T objectToCast)
return new Optional<T>(objectToCast);
然后在你的课堂上使用它
[Serializable]
[XmlRoot(ElementName = "foo")]
public class foo
[XmlElement(ElementName = "myInteger", isNullable = false)]
Optional<int> myInt;
你可以做类似的事情
myFoo.myInt = 7;
int j = 8 + myFoo.myInt;
出于所有目的,它是一个 int。出于序列化目的,它可以为 null 并阻止被序列化。
【讨论】:
谢谢,这对我来说很好用!当将它与另一个自定义数据类型一起使用时(我的布尔值需要序列化为 Y/N),我已将 IComparable 更改为 IComparable这对我有用。
[XmlIgnore]
public float? Speed get; set;
[XmlAttribute("Speed")]
public float SpeedSerializable
get
return this.Speed.Value;
set this.Speed = value;
public bool ShouldSerializeSpeedSerializable()
return Speed.HasValue;
【讨论】:
【参考方案4】:您可以使用XmlElementAttribute.IsNullable:
[Serializable]
public class Result
[XmlElement(IsNullable = true)]
public DateTime? LastUpdated get; set;
【讨论】:
它不能与属性一起使用。它仅用于元素。【参考方案5】:注意:这肯定适用于 WCF 中的 SOAP 合同。我没有在其他 Xml 序列化场景中测试过。
当使用[DataContract]
时,您可以使用
[DataMember(EmitDefaultValue = false)]
boolean
,它只会发出true
的值。
对于nullable boolean
,它只会在不是null
时发出。
对于string
,它只会在不是null
时发出值。
对于int
,它只会在不是0
时发出值。
等等
确保将[DataContract]
放在类本身上,将[DataMember]
放在要序列化的所有成员上,无论您是否指定EmitDefaultValue
。
不建议将 EmitDefaultValue 属性设置为 false 实践。只有在有特殊需要时才应该这样做 (例如为了互操作性或减少数据大小)。
https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.emitdefaultvalue(v=vs.110).aspx
【讨论】:
以上是关于如果它为空或为空,如何从序列化中忽略可为空的属性?的主要内容,如果未能解决你的问题,请参考以下文章