对象反序列化xml就好了,但不是json

时间:2013-02-27 20:17:30

标签: .net serialization asp.net-mvc-4 asp.net-web-api

我发现这是一个非常奇怪的问题。当我向我的web api服务发送xml请求时,每个反序列化都很好。但是,当我发送json请求时,此ONE属性不会反序列化。以下是对象:

[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请求执行相同操作时,将实例化地理标记属性,但其所有值都为null。这个父对象中的其他所有内容都很好。

这是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 个答案:

答案 0 :(得分:2)

显然,Json.net序列化程序的操作顺序肯定存在差异。我想知道它是否试图对性能做一些懒惰的反序列化。无论如何,我写的一个错误揭示了序列化器的不同之处:

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

这永远不会设置私有字段。它应该是:

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

所以我的假设是私有字段永远不会被设置,这就是让我觉得它被设置为本身延迟加载反序列化的原因。所以现在我们已经过了反序列化过程,在私有字段上执行的检查将始终返回null,因此默认返回一个空对象。

答案 1 :(得分: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; }
    }
}