I have a system with many data contracts where the members are decorated with:
[DataMember(EmitDefaultValue = false)]
I have a case where I need the members to be included when null when serialized to JSON. No matter what serializer settings I choose, I can not get this to work.
[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);
}
I have even created a custom data contract resolver which provides additional overrides per property.
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;
}
I've tried all the variations of null value handling and default value handling to ignore the emit default value = false. According to the json net docs, these settings should give me null properties on my object. Before I go debug the the json net source, is there anything else I am missing?
You need to set property.DefaultValueHandling = DefaultValueHandling.Include
rather than DefaultValueHandling.Ignore
in the contract resolver:
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 checks both DefaultValueHandling
and NullValueHandling
before serializing a member, and both checks have to pass in order for the member to be serialized. And, as you have noticed, if either are set explicitly on the contract's property then that will override the settings in JsonSerializerSettings
. This explains why a custom contract resolver is required.
You might want to cache the contract resolver for best performance.