0

In my code I want to use ShouldDeserialize method to make my response more cleaner, but ShouldDeserialize{Property} method is not visible for deserialize method. In below code ShouldSerializeItems predicate works.

public class ItemsContainer
{
    public string Id { get; set; }

    [JsonProperty]
    public IEnumerable<Item> Items{ get; set; }
    //Working
    public bool ShouldSerializeItems()
    {
        return !Items.All(x =>
            string.IsNullOrEmpty(x.ItemName) && string.IsNullOrEmpty(x.ItemId));
    }
    // Not working
    public bool ShouldDeserializeItems()
    {
        return !Items.All(x =>
            string.IsNullOrEmpty(x.ItemName) && string.IsNullOrEmpty(x.ItemId));
    }
}

And call deserialize:

JsonConvert.DeserializeObject<ItemsContainer>(json);

In newtonsoft documentation both serialize and deserialize predicate are documented:

  • You have to post your json too. – Serge Jan 25 '22 at 15:43
  • Am I missing something, or are both Methodes equal? There is no Newtonsoft Methods called – TheTanic Jan 25 '22 at 15:45
  • 1
    `ShouldDeserialize` is not implemented https://stackoverflow.com/questions/35502152/conditional-serialization-deserialization-of-object-properties-with-json-net – Charles Jan 25 '22 at 15:55
  • @Charles Are you sure that it has not been implemented in the last five years? – Peter Csala Jan 25 '22 at 15:57
  • 1
    @PeterCsala it's not working with any property i tested. So i would say it's not – Charles Jan 25 '22 at 15:58
  • 1
    That's right, checking for a property named ShouldDeserializeXXX() and automatically calling it was never implemented, probably because XmlSerializer only ever had support for ShouldSerializeXXX(), and the Json.NET functionality was modeled on that. See: [Conditional serialization/deserialization of object properties with json.net](https://stackoverflow.com/q/35502152/3744182). The infrastructure is there, so you can do it yourself if you need to. – dbc Jan 25 '22 at 18:39
  • 2
    Now that I look at your code, your method `ShouldDeserializeItems()` assumes that the `Items` **have already been deserialized**. Json.NET's `ShouldDeserialize` function is called **before** deserialization, not after. You should use an [`[OnDeserialized]`](https://www.newtonsoft.com/json/help/html/SerializationCallbacks.htm) callback to clear out unwanted items after deserialization. – dbc Jan 25 '22 at 22:47

2 Answers2

1

Checking for a property named named ShouldDeserialize*() and automatically calling it was never implemented by Json.NET. See: Conditional serialization/deserialization of object properties with json.net. The infrastructure is there, so you could do it yourself by implementing a custom contract resolver that overrides DefaultContractResolver.CreateProperty() and sets JsonProperty.ShouldDeserialize.

That being said, it appears that your method ShouldDeserializeItems() assumes that the Items have already been deserialized, then filters them out based on some custom logic. Json.NET's JsonProperty.ShouldDeserialize predicate is called before deserialization, not after. When it returns true the JSON property is skipped with no ability to examine the contents, and thus cannot be used here.

Instead, you should use an [OnDeserialized] callback to clear out unwanted items after deserialization:

[System.Runtime.Serialization.OnDeserialized]
private void OnDeserializedMethod(System.Runtime.Serialization.StreamingContext context)
{       
    if (Items != null && Items.All(x =>
        string.IsNullOrEmpty(x.ItemName) && string.IsNullOrEmpty(x.ItemId)))
        Items = new List<Item>();
}
dbc
  • 104,963
  • 20
  • 228
  • 340
0

But when you are about to deserialize the Items property of the ItemContainer there is likely nothing in the Items property yet. You may not need this predicate because if the ShouldSerialize is working correctly you will never have junk data to deserialize.

Natalia Muray
  • 252
  • 1
  • 6