如何强制 Newtonsoft Json 序列化所有属性?(具有“指定"属性的奇怪行为) [英] How to force Newtonsoft Json to serialize all properties? (Strange behavior with "Specified" property)

查看:24
本文介绍了如何强制 Newtonsoft Json 序列化所有属性?(具有“指定"属性的奇怪行为)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Fellow programmers, I've encountered a strange behavior in Newtonsoft.Json.

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

When I'm trying to serialize an object looking like this:

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

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

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

Using this simple call with no custom converters / binders / contract resolvers:

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

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

or even with JToken.FromObject(...) I always get only one property:

{
   "DMSDocWorkflowIResultSpecified": false
}

当我附加跟踪编写器时,它只捕获以下内容:

When I attach the trace writer, it catches only this:

[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: 
{
  "DMSDocWorkflowIResultSpecified": false
}"

因此,Newtonsoft.Json 似乎有点神奇地对待这个指定"属性.我可以关掉这个吗?我需要这两个属性来生成具有这些名称的 JSON.

So it seems Newtonsoft.Json treats this "Specified" property somewhat magically. Can I turn this off? I need both these properties in resulting JSON with exactly these names.

推荐答案

Json.NET 4.0.1 发行说明:新功能 - 添加了 XmlSerializer 样式指定的属性支持.XmlSerializer 功能依次在 MinOccurs 属性绑定中描述支持:

This behavior is mentioned, very briefly, in the Json.NET 4.0.1 release notes: New feature - Added XmlSerializer style Specified property support. The XmlSerializer functionality is in turn described in MinOccurs Attribute Binding Support:

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

[For optional fields] Xsd.exe generates a public field of type bool whose name is the element field's name with Specified appended. For example, if the element field's name is startDate, the bool field's name becomes startDateSpecified. When serializing an object to XML, the XmlSerializer class checks the value of the bool field to determine whether to write the element.

我觉得这个功能应该被记录在这里,但不是.您可能希望使用 Newtonsoft打开文档问题.

I feel as though this functionality should be documented here, but is not. You might want to open a documentation issue with Newtonsoft.

既然你不想要这种行为,如果你使用 Json.NET 11.0.1 或更高版本,您可以通过实例化您自己的 DefaultContractResolver 和设置 DefaultContractResolver.IgnoreIsSpecifiedMembers = true:

Since you don't want this behavior, if you are using Json.NET 11.0.1 or later, you can disable it for all classes by instantiating your own DefaultContractResolver and settting DefaultContractResolver.IgnoreIsSpecifiedMembers = true:

public static class JsonContractResolvers
{
    // Newtonsoft recommends caching and reusing contract resolvers for best performance:
    // https://www.newtonsoft.com/json/help/html/Performance.htm#ReuseContractResolver
    // But be sure not to modify IgnoreIsSpecifiedMembers after the contract resolver is first used to generate a contract.

    public static readonly DefaultContractResolver IgnoreIsSpecifiedMembersResolver =
        new DefaultContractResolver { IgnoreIsSpecifiedMembers = true };
}

然后将其传递给 JsonConvert 如下:

Then pass it to JsonConvert as follows:

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

或者创建一个 JToken 做:

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

如果您使用的是早期版本,则需要创建并缓存一个 自定义合同解析器:

If you are using an earlier version, you will need to create and cache a custom contract resolver:

public static class JsonContractResolvers
{
    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;
    }
}

这篇关于如何强制 Newtonsoft Json 序列化所有属性?(具有“指定"属性的奇怪行为)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆