【问题标题】:JSON.net not including null properties with EmitDefaultValue falseJSON.net 不包括 EmitDefaultValue 为 false 的空属性
【发布时间】:2016-08-15 18:31:39
【问题描述】:

我有一个包含许多数据合同的系统,其中成员被装饰:

[DataMember(EmitDefaultValue = false)]  

我有一个案例,当序列化为 JSON 时,我需要在 null 时包含成员。无论我选择什么序列化程序设置,我都无法让它工作。

   [TestMethod]
    public void SerializationTest()
    {

        var contract = Activator.CreateInstance(typeof(TestContract));

        var formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Include,
                DefaultValueHandling = DefaultValueHandling.Ignore,
                TypeNameHandling = TypeNameHandling.All,
                ContractResolver = new DataContractResolver(),
                Binder = new DataContractBinder()
            }
        };

        var result = JsonConvert.SerializeObject(contract, formatter.SerializerSettings);
    }

我什至创建了一个自定义数据协定解析器,它为每个属性提供额外的覆盖。

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {                        
        var property = base.CreateProperty(member, MemberSerialization.Fields);                        
        property.NullValueHandling = NullValueHandling.Include;            
        property.DefaultValueHandling = DefaultValueHandling.Ignore;
        property.ShouldSerialize = o => true;
        return property;
    }

我已经尝试了空值处理和默认值处理的所有变体来忽略发出默认值 = false。根据 json net docs,这些设置应该为我的对象提供 null 属性。在我去调试 json 网络源之前,我还缺少什么吗?

【问题讨论】:

    标签: .net json.net datacontracts


    【解决方案1】:

    你需要在合约解析器中设置property.DefaultValueHandling = DefaultValueHandling.Include而不是DefaultValueHandling.Ignore

    public class DataContractResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            var property = base.CreateProperty(member, memberSerialization);
            property.NullValueHandling = NullValueHandling.Include;
            property.DefaultValueHandling = DefaultValueHandling.Include;
            property.ShouldSerialize = o => true;
            return property;
        }
    }
    

    Json.NET 在序列化成员之前同时检查DefaultValueHandlingNullValueHandling,并且这两项 检查都必须通过才能使成员序列化。而且,正如您所注意到的,如果在合同的属性上明确设置了任何一个,那么这将覆盖JsonSerializerSettings 中的设置。这解释了为什么需要自定义合同解析器。

    您可能想cache the contract resolver 以获得最佳性能。

    【讨论】:

    • 有趣。我在配置 SerializerSettings 时尝试过这种设置组合。我在覆盖中也没有这样做,因为文档听起来像是无论如何你都应该使用忽略。如果使用这些设置并使用自定义解析器,它确实有效。似乎更好的方法是告诉设置是否允许覆盖属性。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 2013-03-11
    相关资源
    最近更新 更多