你的问题的简短回答是,自动检查ShouldDeserialize{PropertyName}()
目前尚未实施,尽管ShouldSerialize{PropertyName}()
is.接下来是更长的答案和解决方法。
班上JsonProperty http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_JsonProperty.htm由 Json.NET 在内部使用来定义如何将 JSON 属性映射到 .NET 成员或构造函数参数的协定。它有两个谓词属性,ShouldSerialize http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_ShouldSerialize.htm and ShouldDeserialize http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_ShouldDeserialize.htm当非空时,分别阻止属性被序列化和反序列化。初始化每个JsonProperty
是的工作ContractResolver http://www.newtonsoft.com/json/help/html/ContractResolver.htm。对于每个属性{PropertyName}
, Json.NET 的默认合约解析器 http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_DefaultContractResolver.htm自动检查是否存在public bool ShouldSerialize{PropertyName}() https://msdn.microsoft.com/en-us/library/53b8022e%28v=vs.110%29.aspx方法。如果存在这样的方法,它会在ShouldSerialize
谓词,从而在方法返回时抑制序列化false
。这是因为通过方法控制属性序列化而实现的ShouldSerialize{PropertyName}()
是一个标准模式,例如,XmlSerializer https://stackoverflow.com/questions/5818513/xml-serialization-hide-null-values。有关更多背景信息,请参阅相关内容Json.NET 发行说明 http://james.newtonking.com/archive/2010/04/16/json-net-3-5-release-7-bson-binary-json-part-deux.
例如,在下面的类中,序列化MyObjectData
将被压制,除非MyObjectData.Count > 0
:
class MyObject
{
public DataDictionary MyObjectData { get; set; }
public bool ShouldSerializeMyObjectData() { return MyObjectData != null && MyObjectData.Count > 0; }
}
JsonProperty.ShouldDeserialize
, 然而,默认合约解析器永远不会设置它。这可能是因为没有相当于反序列化的标准模式ShouldSerialize{PropertyName}()
因此 Newtonsoft 从未收到任何实施此类模式的请求。然而,正如您所注意到的,支持这种模式的基础设施是存在的,因此应用程序可以创建自定义合约解析器 http://www.newtonsoft.com/json/help/html/CustomContractResolver.htm就是这样做的。事实上,Json.NET 自己有一个这样的契约解析器的例子测试套件 https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json.Tests/Serialization/ShouldSerializeTests.cs:
public class ShouldDeserializeContractResolver : DefaultContractResolver
{
public static new readonly ShouldDeserializeContractResolver Instance = new ShouldDeserializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
MethodInfo shouldDeserializeMethodInfo = member.DeclaringType.GetMethod("ShouldDeserialize" + member.Name);
if (shouldDeserializeMethodInfo != null)
{
property.ShouldDeserialize = o => { return (bool)shouldDeserializeMethodInfo.Invoke(o, null); };
}
return property;
}
}
public class ShouldDeserializeTestClass
{
[JsonExtensionData]
public IDictionary<string, JToken> ExtensionData { get; set; }
public bool HasName { get; set; }
public string Name { get; set; }
public bool ShouldDeserializeName()
{
return HasName;
}
}
如果您想有条件地抑制属性的反序列化,即使属性存在于 JSON 中,您也可以使用此契约解析器。
Notes:
-
如果您确实使用自定义合同解析器,您应该缓存并重用它 https://www.newtonsoft.com/json/help/html/Performance.htm#ReuseContractResolver以获得最佳性能。
-
JsonProperty.ShouldDeserialize
在反序列化属性值之前调用。如果返回 true,则跳过该属性,无法检查该属性的内容。因此它不能用于基于该值实现自定义过滤。
-
JSON 对象的定义是JSON标准 https://www.json.org/json-en.html as an 无序的一组名称/值对。因此一个ShouldDeserialize
假设其他属性已被读入的方法可能是brittle https://en.wikipedia.org/wiki/Software_brittleness.
相反,如果您想根据另一个属性的值跳过一个属性的反序列化,请考虑使用[OnDeserialized] https://www.newtonsoft.com/json/help/html/SerializationCallbacks.htm反序列化所有属性后,回调并清除不需要的值。