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

Mic*_*dej 13 c# serialization json.net

各位程序员,我在Newtonsoft.Json中遇到过一个奇怪的行为.

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

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

    [JsonProperty("DMSDocWorkflowIResultSpecified")]
    public bool DMSDocWorkflowIResultSpecified { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

var testObject = new DMSDocWorkflowI();
var json = JsonConvert.SerializeObject(testObject, Formatting.Indented);
Run Code Online (Sandbox Code Playgroud)

或者甚至JToken.FromObject(...)我总是只得到一处房产:

{
   "DMSDocWorkflowIResultSpecified": false
}
Run Code Online (Sandbox Code Playgroud)

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

[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}"
Run Code Online (Sandbox Code Playgroud)

所以似乎Newtonsoft.Json有些神奇地对待这个"Specified"属性.我能把它关掉吗?我在生成的JSON中需要这些属性以及这些名称.

dbc*_*dbc 11

Json.NET 4.0.1发行说明中非常简要地提到了这种行为:新功能 - 添加了XmlSerializer样式指定的属性支持.该功能又在MinOccurs属性绑定支持中描述:XmlSerializer

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

我觉得这个功能应该记录在这里,但事实并非如此.您可能想要打开 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 };
}
Run Code Online (Sandbox Code Playgroud)

然后将其传递给JsonConvert如下:

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

或者创建一个JTokendo:

var jToken = JToken.FromObject(testObject, JsonSerializer.CreateDefault(settings));
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)