2013-04-23 64 views
1

我有一個用於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; 
     } 
+5

你見過這個http://stackoverflow.com/questions/244953/serialize-a-nullable-int?rq=1 – Yahya 2013-04-23 14:56:59

+0

你有什麼期待XML的樣子?在這種情況下,如果屬性爲null,則會得到'';你可以後處理你的XML(更容易),或者你可以寫一個XmlWriter類(更難,表現更好)。還有其他的選項既困難又膨脹你的代碼。 – 2013-04-23 14:57:57

+0

不,我只是想忽略xmlattribute,如果它是空的。但是DateTime?不可序列化。如何更換它? – 2013-04-23 15:09:13

回答

6

可空不直接XmlSerialization支持。

如果您要使用可空屬性,您必須使用非空屬性,並添加一個帶有後綴「Specified」的屬性相同名稱的布爾屬性,該屬性必須在該屬性必須可序列化時指定。

一個例子與你的情況:

private DateTime? _lastUpdated; 

    [XmlAttribute("lastUpdated")] 
    public DateTime LastUpdated { 
     get { 
      return (DateTime)_lastUpdated; 
     } 
     set 
     { 
      _lastUpdated = value; 
     } 
    } 

    public bool LastUpdatedSpecified 
    { 
     get 
     { 
      return _lastUpdated.HasValue; 
     } 
    } 
+0

謝謝,但問題是我無法使用XmlSerializer對它進行序列化。我得到這個錯誤:+ \t \t InnerException \t {「反映屬性'LastUpdated'有錯誤。」} \t System.Exception {System.InvalidOperationException} – 2013-04-24 07:29:55

+0

對不起,我速度太快了,我正確並編輯了我的代碼。你可以試試這個嗎? – binard 2013-04-24 08:22:36

+0

@TheLight你能接受我的答案,就像最好的迴應? – binard 2014-04-28 07:56:49

2

您可以使用XmlElementAttribute.IsNullable

[Serializable] 
public class Result 
{ 
    [XmlElement(IsNullable = true)] 
    public DateTime? LastUpdated { get; set; } 
} 
+0

它不能與屬性一起使用。它僅用於元素。 – belurd 2016-04-05 09:44:57

2

我知道這個話題了。這是我帶來的解決方案。一個封裝了類型的類,並且具有對類型的隱式轉換。在序列化時,成員變量可以標記爲IsNullable = false而不會收到編譯器錯誤,並在空值時阻止其被序列化。

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所有目的。爲了序列化目的,它可以是空的並且被阻止被序列化。

1

這是爲我工作。

[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; 
    } 
+0

這對我來說非常合適。謝謝! – JohnW 2017-01-20 21:00:57

0

注意:這在WCF的SOAP合同中肯定適用。我沒有在其他Xml序列化場景中測試過。

當使用[DataContract]可以使用

[DataMember(EmitDefaultValue = false)]

  • 對於boolean如果是true它只會發出值。
  • 對於nullable boolean它只會發出,如果它不是null
  • 對於string如果它不是null它只會發出的值。
  • 對於int如果不是0它只會發出的值。

確保把[DataContract]類本身和[DataMember]你想要序列化,不管你指定EmitDefaultValue與否所有成員。

Setting the EmitDefaultValue property to false is not a recommended practice. It should only be done if there is a specific need to do so (such as for interoperability or to reduce data size).

https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.emitdefaultvalue(v=vs.110).aspx