如何强制Newtonsoft Json序列化所有属性? (“指定”属性的奇怪行为)

同事们,我在Newtonsoft.Json中遇到过一个奇怪的行为。

当我试图序列化一个看起来像这样的对象:

public class DMSDocWorkflowI { [JsonProperty("DMSDocWorkflowIResult")] public bool DMSDocWorkflowIResult { get; set; } [JsonProperty("DMSDocWorkflowIResultSpecified")] public bool DMSDocWorkflowIResultSpecified { get; set; } } 

使用这个简单的调用,没有自定义转换器/绑定器/合同解析器:

 var testObject = new DMSDocWorkflowI(); var json = JsonConvert.SerializeObject(testObject, Formatting.Indented); 

或者甚至使用JToken.FromObject(...)我总是只获得一个属性:

 { "DMSDocWorkflowIResultSpecified": false } 

当我附加跟踪编写器时,它只捕获这个:

 [0]: "2016-08-30T11:06:27.779 Info Started serializing *****DMSDocWorkflowI. Path ''." [1]: "2016-08-30T11:06:27.779 Verbose IsSpecified result for property 'DMSDocWorkflowIResult' on *****DMSDocWorkflowI: False. Path ''." [2]: "2016-08-30T11:06:27.779 Info Finished serializing *****.DMSDocWorkflowI. Path ''." [3]: "2016-08-30T11:06:27.780 Verbose Serialized JSON: \r\n{\r\n \"DMSDocWorkflowIResultSpecified\": false\r\n}" 

所以似乎Newtonsoft.Json有些神奇地对待这个“Specified”属性。 我能把它关掉吗? 我在结果JSON中需要这两个属性,并且具有这些名称。

在Json.NET 4.0.1发行说明中 非常简要地提到了这种行为: 新function – 添加了XmlSerializer样式指定的属性支持 。 然后在MinOccurs属性绑定支持中描述XmlSerializerfunction:

[对于可选字段] Xsd.exe生成bool类型的公共字段,其名称是附加了Specified的元素字段名称。 例如,如果元素字段的名称是startDate,则bool字段的名称将变为startDateSpecified。 将对象序列化为XML时,XmlSerializer类检查bool字段的值以确定是否要写入该元素。

我觉得这个function应该记录在这里 ,但事实并非如此。 您可能想要打开 Newtonsoft 的文档问题 。

由于您不希望出现此行为,因此如果您使用的是Json.NET 11.0.1或更高版本 ,则可以通过实例化自己的DefaultContractResolver并设置DefaultContractResolver.IgnoreIsSpecifiedMembers = true来禁用所有类:

 public static class JsonContractResolvers { // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. // http://www.newtonsoft.com/json/help/html/ContractResolver.htm // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." public static readonly DefaultContractResolver IgnoreIsSpecifiedMembersResolver = new DefaultContractResolver { IgnoreIsSpecifiedMembers = true }; } 

然后将其传递给JsonConvert ,如下所示:

 var settings = new JsonSerializerSettings { ContractResolver = JsonContractResolvers.IgnoreIsSpecifiedMembersResolver }; var json = JsonConvert.SerializeObject(testObject, Formatting.Indented, settings); 

或者创建一个JToken做:

 var jToken = JToken.FromObject(testObject, JsonSerializer.CreateDefault(settings)); 

如果您使用的是早期版本,则需要创建并缓存自定义合约解析程序 :

 public static class JsonContractResolvers { // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. // http://www.newtonsoft.com/json/help/html/ContractResolver.htm // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." public static readonly DefaultContractResolver IgnoreIsSpecifiedMembersResolver = new IgnoreSpecifiedContractResolver(); } internal class IgnoreSpecifiedContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); property.GetIsSpecified = null; property.SetIsSpecified = null; return property; } }