Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ShouldSerialize method is not triggered in .NET Core 3

I normally use ShouldSerialize to exclude properties that have no data such as array but now, it does not appear to be triggered when I'm only using JSON serializer in .NET Core 3. It was being triggered when using NewtonSoft but I've removed it from my project since it no longer appears to be required.

For example:

    private ICollection<UserDto> _users;

    public ICollection<UserDto> Users
    {
        get => this._users ?? (this._users = new HashSet<UserDto>());
        set => this._users = value;
    }

    public bool ShouldSerializeUsers()
    {
        return this._users?.Count > 0;
    }

Any ideas why ShouldSerializeUsers is not being triggered?

I've seen other answers where you can use:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddJsonOptions(options => { 
        options.SerializerSettings.NullValueHandling = 
        NullValueHandling.Ignore;
    });
}

But I'd like to know if there is another way to handle this as I'm not using .AddMvc

Thanks.

like image 943
Thierry Avatar asked Dec 13 '22 09:12

Thierry


2 Answers

The reason that your ShouldSerialize is not triggered in ASP.NET Core 3.0 is that, in this and subsequent versions of ASP.NET, a different JSON serializer is being used by default, namely System.Text.Json.JsonSerializer. See:

  • Try the new System.Text.Json APIs.
  • Breaking changes to Microsoft.AspNetCore.App in 3.0 #325.
  • The future of JSON in .NET Core 3.0 #90.

Unfortunately as of .NET Core 3.1 this serializer does not support the ShouldSerializeXXX() pattern; if it did it would be somewhere in JsonSerializer.Write.HandleObject.cs -- but it's not. The following issues track requests for conditional serialization:

  • .net core 3.0 system.text.json option for ignoring property at runtime like newstonsoft DefaultContractResolver #42043.

  • System.Text.Json option to ignore default values in serialization & deserialization #779.

To restore ShouldSerialize functionality, you can revert back to using Newtonsoft as shown in this answer to Where did IMvcBuilder AddJsonOptions go in .Net Core 3.0? by poke, and also Add Newtonsoft.Json-based JSON format support:

  1. Install Microsoft.AspNetCore.Mvc.NewtonsoftJson.
  2. Then call AddNewtonsoftJson() in Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers()
            .AddNewtonsoftJson();
    }
    
like image 96
dbc Avatar answered Jan 02 '23 04:01

dbc


It is possible in Net 5 to use conditional JsonIgnore. It does not give you full conditional option, but you can exclude null at least which I suppose is the most used case:

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? MyProperty { get; set; }

If one wants to allow for optional null in json, it is possible to use a custom Optional<T> struct that is similar to Nullable, like e.g. one from Roslyn. Then it's possible to have a value, null, or no field at all in the result JSON.

like image 25
Ilya Chernomordik Avatar answered Jan 02 '23 03:01

Ilya Chernomordik