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

本文关键字:序列化 JSON 字符串 DatacontractJSON 程序 对象 我们 Net | 更新日期: 2023-09-27 18:28:16

我有一个类似的类

[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 实现同样的效果吗

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

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

TLDR:将其添加到WebApiConfig.cs:

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

除非您总是从WCF到WCF进行通信,否则最好的选择可能是使用Newtonsoft序列化程序。不幸的是,MS序列化程序似乎遵循了一些特定于Microsoft的标准,这些标准与许多web应用程序所期望的标准不匹配。

Newtonsoft的序列化程序似乎更标准,甚至MS也将其用于WebAPI,并在Web API http客户端中使用(nuget将为您删除它)。

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

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

您可能会看到另一件事:

DataContractJsonSerializer和Newtonsoft之间的差异仍然存在,但至于为什么会出现奇怪的序列化行为,则是混合了序列化标准。

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

如果您想以datacontract的方式执行此操作,请使用改为[DataContract]属性,并用[DataMember]属性标记要序列化的每个公共成员。(或者删除所有序列化属性,它应该默认为所有公共属性)

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

Newtonsoft.Json.dll中的DefaultContractResolver类我发现了一些将IgnoreSerializableAttribute属性设置为true的代码。
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE || PORTABLE40)
    IgnoreSerializableAttribute = true;
#endif

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

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

如果你这样做,你会发现相同的json字符串会像使用其他类一样输出。您遇到的问题是由于两个序列化程序处理默认序列化的方式不同(没有指定其他信息):

  1. DataContract序列化所有私有字段,除非另有指定

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

关于如何使Newtonsoft序列化私有字段,我没有其他想法,只能制作一个具有m_Width和m_Height属性的包装类,在setter和geter上将值放入实际对象的正确目标属性中