Conditional serialization / deserialization of object properties using json.net

I have a script with the class defined below:

class MyObject { public DataDictionary MyObjectData { get; set; } public bool ShouldSerializeMyObjectData() { return true; } public bool ShouldDeserializeMyObjectData() { return false; } } 

When I try to serialize / deserialize this class using JSON.net, it takes into account ShouldSerialize , but not ShouldDeserialize .

According to the documentation, both should work just as I assume. Is there anything special I should know? More generally, how do I handle scripts where I want to serialize a property but not deserialize it?

I am using Json.NET 8.0 if that matters.

Thank you for your help.

+5
source share
1 answer

A short answer to your question: Automatic checking ShouldDeserialize{PropertyName}() is currently not implemented, although ShouldSerialize{PropertyName}() is. What follows is a longer answer and a workaround.

The JsonProperty class JsonProperty used internally by Json.NET to define a contract on how to map a JSON property to a .NET member or constructor. It has two predicate properties: ShouldSerialize and ShouldDeserialize that with nonzero values ​​you cannot serialize and deserialize a property, respectively. Initializing each JsonProperty is the job of ContractResolver . For each property {PropertyName} , the Json.NET default contract resolver automatically checks for the presence of public bool ShouldSerialize{PropertyName}() . If such a method exists, it adds a call to it in the ShouldSerialize predicate, thereby suppressing serialization when the method returns false . This was implemented because controlling the serialization of properties using the ShouldSerialize{PropertyName}() method is a standard template supported, for example, by XmlSerializer . See the relevant Json.NET release notes for more information.

For example, in the following class, the serialization of MyObjectData will be suppressed if MyObjectData.Count > 0 :

 class MyObject { public DataDictionary MyObjectData { get; set; } public bool ShouldSerializeMyObjectData() { return MyObjectData != null && MyObjectData.Count > 0; } } 

JsonProperty.ShouldDeserialize , however, it is never set using the default contract JsonProperty.ShouldDeserialize . This may be due to the fact that there is no standard template for deserialization equivalent to ShouldSerialize{PropertyName}() , and therefore Newtonsoft has never had requests to implement such a template. However, as you noticed, there is an infrastructure to support such a template, so applications can create custom contract adapters that do just that. In fact, Json.NET has an example of such a contract recognizer in its own test suite :

 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; } } 

If you want to conditionally suppress deserialization of properties, even if they are present in JSON, you can use (and caching ) this contract resolver.

+6
source

Source: https://habr.com/ru/post/1243382/


All Articles