1

我发现这是一个非常奇怪的问题。当我向我的 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 请求执行相同操作时,geotag 属性被实例化,但其所有值均为空。此父对象中的其他所有内容都很好。

这是 json 请求中的属性:

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

注意属性 getterget { return _geotag ?? new GeotagInfo(); }

xml请求对此没有问题。但是,如果我删除它并制作它,get { return _geotag; }那么问题就会消失。不幸的是,这会导致服务更深层次的其他问题。

这里发生了什么?它如何与 xml 而不是 json 一起正常工作(除非我删除了默认的 getter)。我知道 MVC4 使用 json.net,所以这可能与它有关。

注意:正如其他线程中所建议的,我尝试从类中删除可序列化的属性。没变。

4

2 回答 2

2

显然,Json.net 序列化程序的操作顺序肯定存在差异。我想知道它是否正在尝试进行某种惰性反序列化以提高性能。无论如何,我写了一个错误,它揭示了序列化程序的差异:

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

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

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

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

于 2013-03-20T04:19:53.050 回答
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; }
    }
}
于 2013-02-27T20:20:55.987 回答