2013-02-27 51 views
1

我發現這是一個非常奇怪的問題。當我發送一個XML請求到我的web api服務時,每個反序列化就好了。但是,當我發送json請求時,這個ONE屬性不會反序列化。以下是對象:對象反序列化xml很好,但不是json

[Serializable] 
[DataContract(Namespace = "")] 
public class TransactionData 
{ 
    // bunch of other properties that are unaffected ... 

    private GeotagInfo _geotag; 

    [DataMember(IsRequired = false, Name = "GeotagInfo", Order = 7)] 
    public GeotagInfo GeotagInfo 
    { 
     get { return _geotag ?? new GeotagInfo(); } 
     set { _geotag = value; } 
    } 
} 


[DataContract(Namespace = "")] 
public class GeotagInfo 
{ 

    [DataMember(IsRequired = false, Name = "Longitude", Order = 1, EmitDefaultValue = false)] 
    public string Longitude { get; set; } 

    [DataMember(IsRequired = false, Name = "Latitude", Order = 2, EmitDefaultValue = false)] 
    public string Latitude { get; set; } 

    [Image(Nullable = true)] 
    [DataMember(IsRequired = false, Name = "MapImage", Order = 3, EmitDefaultValue = false)] 
    public string MapImage { get; set; } 

    [XmlIgnore] 
    public int TransactionId { get; set; } 
} 

當在控制器的入口點處使用xml請求中斷時。地理標記屬性在那裏,並且已滿。當我對json請求執行相同操作時,geotag屬性將被實例化,但其所有值都爲空。這個父對象中的其他東西都很好。

這是JSON請求屬性:

"GeotagInfo": { 
    "Longitude": "-yy.yyyy", 
    "Latitude": "xx.xxxx", 
    "MapImage": "base64 string" 
} 

通知屬性getter get { return _geotag ?? new GeotagInfo(); }

XML請求沒有問題與此有關。但是,如果我刪除它並使其成爲get { return _geotag; },那麼問題就會消失。不幸的是,這會導致服務更深入的其他問題。

這是怎麼回事?它如何與XML而不是JSON(除非我刪除默認的getter)正常工作。我知道MVC4使用json.net,所以這可能與它有關。

注意:正如其他線程所建議的,我嘗試從類中移除可序列化的屬性。不用找了。

回答

2

因此很明顯,肯定是在操作與Json.net串行順序的差異。我不知道它是否試圖做一些懶惰的反序列化的表現。無論如何,有我寫了一個錯誤,這揭示了序列化的區別:

get { return _geotag ?? new GeotagInfo(); } 

這是永遠不落的私人領域。它應該是:

get { return _geotag ?? (_geotag = new GeotagInfo()); } 

所以我的假設是,私人領域從來沒有得到建立,這是什麼讓我覺得它設置爲天生懶惰負載反序列化。所以,現在我們已經超過了反序列化過程,在私有字段上執行的檢查將始終返回null,因此默認返回一個空對象。

1

一種解決方法是創建兩個屬性,一個是序列化,另一個用於進一步的使用:

[Serializable] 
[DataContract(Namespace = "")] 
public class TransactionData 
{ 
    // bunch of other properties that are unaffected ... 

    private GeotagInfo _geotag; 

    [DataMember(IsRequired = false, Name = "GeotagInfo", Order = 7)] 
    public DataMember_GeotagInfo GeotagInfo 
    { 
     get; 
     set; 
    } 

    public GeotagInfo GeotagInfo 
    { 
     get { return DataMember_GeotagInfo ?? new GeotagInfo(); } 
     set { DataMember_GeotagInfo = value; } 
    } 
}