Inspired by the solution from @dbc in the quoted post, I adapted it to apply DefaultValueHandling to a whole class.
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;
}
}
Then I can serialize this way:
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);
And voila, I get the expected result.