如何强制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属性绑定支持中描述XmlSerializer
function:
[对于可选字段] 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; } }