当我们使用JSON.Net序列化可序列化对象时,JSON字符串与DatacontractJSON序列化程序不同

时间:2013-08-19 13:23:42

标签: c# wcf

我有一个课程,如下面的

[Serializable]
public class sample
{
    private int m_width;
    private int m_height;
    public int Width
    {
        get
        {
            return this.m_width;
        }
        set
        {
            this.m_width = value;
        }
    }

    public int Height
    {

        get
        {
            return this.m_height;
        }
        set
        {
            this.m_height = value;
        }
    }
}

如果我使用DataContractJsonSerializer来序列化此类的对象,我会得到json字符串,如下所示:

{"m_height":1345,"m_width":1234}

如果我使用Newtonsoft.Json.dll来序列化这个,我会得到如下的输出:

{"Width":1234,"Height":1345}

如果类标记为可序列化,为什么DataContractSerializer使用支持字段进行序列化?

有什么方法可以使用Newtonsoft.Json.dll

实现同样的目的

5 个答案:

答案 0 :(得分:2)

我们有一些标记为[Serializable]的对象,因此可以使用传统方法对它们进行序列化,但我们需要在JSON中对其进行干净序列化以便与Web API一起使用。将IgnoreSerializableAttribute设置为true会阻止Newtonsoft.Json表现得像微软的串行器,而只是序列化公共属性。

TLDR:将其添加到WebApiConfig.cs:

((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;

答案 1 :(得分:1)

除非您始终从WCF与WCF进行通信,否则最好的选择可能是使用Newtonsoft序列化程序。不幸的是,MS序列化程序似乎遵循一些微软特定的标准,这些标准与许多网络应用所期望的标准不符。

Newtonsoft的序列化程序似乎更标准,甚至MS也将它用于WebAPI,而在Web API http客户端(nuget会为你拉下它)。

这是您将找到的另一个区别 - 尝试序列化DateTime类型。您会发现DataContract序列化器以不同的格式序列化该值,该格式与其他JSON不兼容(您会注意到其中的一些斜杠)。我的理解是,某些AJAX WebForm控件使用了这种替代格式,但它特定于Microsoft Webforms。

以下是关于日期的更多信息:http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx

答案 2 :(得分:1)

这是你可能会看到的另一件事:

DataContractJsonSerializer和Newtonsoft之间的差异仍然存在,但是为什么你会得到奇怪的序列化行为 - 你正在混合你的序列化标准。

[Serializable]属性适用于较旧的.Net序列化。 DataContractSerialization是向后兼容的,但行为可能不同。

如果你想以datacontract的方式做这件事,请用。标记你的课程 改为[DataContract]属性,并使用[DataMember]属性标记要序列化的每个公共成员。 (或删除所有序列化属性,它应默认为所有公共属性)

这应该解释看到的差异,但我仍然建议您更喜欢Newtonsoft序列化器。

答案 3 :(得分:1)

Newtonsoft.Json.dll中的DefaultContractResolver类我发现了一些将IgnoreSerializableAttribute属性设置为true的代码。

#if !(SILVERLIGHT || NETFX_CORE || PORTABLE || PORTABLE40)
    IgnoreSerializableAttribute = true;
#endif

我正在使用DotNet4.0 dll,因此该属性设置为true,它忽略了Serializable属性。如果我将其设为false,则它提供与DataContractSerializer相同的输出

答案 4 :(得分:0)

DataContract序列化程序要求您使用[DataContract]属性显式标记该类,然后使用[DataMember]属性标记要序列化的每个所需属性。

如果你这样做,你会发现相同的json字符串将使用另一个类。 您遇到的问题是由于2个序列化程序如何处理默认序列化(未指定其他信息)的差异:

  1. 除非另有说明,否则DataContract会序列化所有私有字段

  2. NewtonSoft序列化所有公共属性,除非另有说明

  3. 关于如何使Newtonsoft序列化私有字段除了使用m_Width和m_Height属性创建包装类之外,我不知道如何在setter和geters上将值放在实际对象的正确目标属性中