我有一个包含许多数据合约的系统,其成员用以下内容进行装饰:
[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;
}
我已经尝试了空值处理和默认值处理的所有变体来忽略emit默认值= false。根据json net docs,这些设置应该为我的对象提供null属性。在我调试json网络源代码之前,还有什么我想念的吗?
答案 0 :(得分:5)
您需要在合约解析器中设置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在序列化成员之前检查DefaultValueHandling
和NullValueHandling
,并且两个检查都必须通过才能序列化成员。而且,正如您所注意到的,如果在合同的属性上明确设置了任何一个,那么它将覆盖JsonSerializerSettings
中的设置。这解释了为什么需要定制合同解析器。
您可能希望cache the contract resolver获得最佳效果。