【问题标题】:How to make DefaultValueHandling only apply to certain classes or members?如何使 DefaultValueHandling 仅适用于某些类或成员?
【发布时间】:2021-07-29 14:24:49
【问题描述】:

我需要让对象的某些部分序列化默认值,而有些则不需要。

在下面的帖子中,我了解如何根据类型执行此操作: Json.NET: How to make DefaultValueHandling only apply to certain types?

但是这个解决方案只适用于类型,不会递归。

预期行为:

{
  {
    "keepDefaults" : {
      "prop1" : true,
      "prop2" : false,
    },
    "ignoreDefaults" : {
      "prop3" : true,
      "prop4" : false,
    }
}

重新序列化时:

  {
    "keepDefaults" : {
      "prop1" : true,
      "prop2" : false
    },
    "ignoreDefaults" : {
      "prop3" : true
    }
}

有什么我可以在 ContractProvider 中覆盖的东西,或者我可以添加到成员或类中以选择 DefaultValueHandling 的属性吗?

【问题讨论】:

标签: c# jsonserializer


【解决方案1】:

受到@dbc 在quoted post 中的解决方案的启发,我对其进行了调整,以将 DefaultValueHandling 应用于整个类。

public class DefaultValueContractResolver : DefaultContractResolver
{
    readonly Dictionary<Type, DefaultValueHandling> _overrides = new Dictionary<Type, DefaultValueHandling>();

    public DefaultValueContractResolver(IEnumerable<KeyValuePair<Type, DefaultValueHandling>> overrides = null) : base()
    {
        _overrides = overrides?.ToDictionary(p => p.Key, p => p.Value) ?? _overrides;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if (property.DefaultValueHandling == null)
        {
            if(_overrides.TryGetValue(property.DeclaringType, out DefaultValueHandling handling))
                property.DefaultValueHandling = handling;
        }
    
        return property;
    }
}

那我可以这样序列化:

var keepDefaults = new KeepDefaults
{
    Prop1 = true,
    Prop2 = false
};

var ignoreDefaults = new IgnoreDefaults
{
    Prop3 = true,
    Prop4 = false
};

var jsSettings = new JsonSerializerSettings
{
    //DefaultValueHandling = DefaultValueHandling.Populate,
    ContractResolver = new DefaultValueContractResolver(
        new Dictionary<Type, DefaultValueHandling>
        { 
            { typeof(IgnoreDefaults), DefaultValueHandling.Ignore } ,
            { typeof(KeepDefaults), DefaultValueHandling.Populate } 
        }),
    Converters = new List<JsonConverter> { new Newtonsoft.Json.Converters.StringEnumConverter() },
    Formatting = Formatting.Indented
};



var json1 = JsonConvert.SerializeObject(keepDefaults, settings);
var json2 = JsonConvert.SerializeObject(ignoreDefaults, settings);

瞧,我得到了预期的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多