Newtonsoft.Json
Newtonsoft.Json copied to clipboard
When using both `DefaultValueHandling.Ignore` and `NullValueHandling.Ignore`, the nullable<int> field is serialized when value is default(int)
When using both DefaultValueHandling.Ignore and NullValueHandling.Ignore, the field is serialized
Source/destination types
public class Test
{
public int? IgnoresNull = null;
public int? IgnoreZeroPlease = 0;
}
Source/destination JSON
{"IgnoreZeroPlease": 0}
Expected behavior
{}
Ignores both null as well as default(int).
Actual behavior
Only ignores null
Is the best solution to fix this to provide a ValueConvertor that returns Null when the default is specified?
This seems to work, but it feels ugly:
protected override IValueProvider CreateMemberValueProvider(MemberInfo member)
{
IValueProvider parent = base.CreateMemberValueProvider(member);
var type = (member as FieldInfo)?.FieldType
?? (member as PropertyInfo)?.PropertyType;
if (type == typeof(decimal?))
{
return new DefaultToNullValueProvider<decimal>(parent);
}
...
With:
internal class DefaultToNullValueProvider<T> : IValueProvider
where T : struct
{
private IValueProvider _parent;
internal DefaultToNullValueProvider(IValueProvider parent)
{
_parent = parent;
}
public object GetValue(object target)
{
object o = _parent.GetValue(target);
var value = (T?)o;
if (value != null && value.HasValue && value.Value.Equals(default(T)))
{
return null;
}
return o;
}
public void SetValue(object target, object value)
{
_parent.SetValue(target, value);
}
}
When using both
DefaultValueHandling.IgnoreandNullValueHandling.Ignore, the field is serializedSource/destination types
public class Test { public int? IgnoresNull = null; public int? IgnoreZeroPlease = 0; }Source/destination JSON
{"IgnoreZeroPlease": 0}Expected behavior
{}Ignores both
nullas well asdefault(int).Actual behavior
Only ignores
nullIs the best solution to fix this to provide a ValueConvertor that returns Null when the default is specified?
This has been logged a long time ago but the behavior is correct when you look at it from a deserialization point of view. If you try deserialize "{}" there would be no way to distinguish between a null or default property. Nullable properties can thus inherently never apply the default property and null rule simultaneously.