Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ignore false values with System.Text.Json

I'm migrating from Newtonsoft.Json to System.Text.Json in my .NET Core 3.0 application. I'm trying to ignore false values.

In System.Text.Json I found the option to ignore null values:

JsonSerializerOptions.IgnoreNullValues = true;

But I cannot find the option to ignore false values in System.Text.Json.

Does someone know how can this be achieved with System.Text.Json?

Or if someone know the equivalent of Newtonsoft DefaultValueHandling = DefaultValueHandling.Ignore option that would be fantastic too.

like image 662
stevo Avatar asked Oct 03 '19 18:10

stevo


People also ask

How do I ignore fields in JSON?

If there are fields in Java objects that do not wish to be serialized, we can use the @JsonIgnore annotation in the Jackson library. The @JsonIgnore can be used at the field level, for ignoring fields during the serialization and deserialization.

How do I ignore JSON property based on condition?

To ignore individual properties, use the [JsonIgnore] attribute. You can specify conditional exclusion by setting the [JsonIgnore] attribute's Condition property. The JsonIgnoreCondition enum provides the following options: Always - The property is always ignored.

Is polymorphic deserialization possible in system text JSON?

Text. Json doesn't support the serialization of polymorphic type hierarchies. For example, if a property's type is an interface or an abstract class, only the properties defined on the interface or abstract class are serialized, even if the runtime type has additional properties.

What is System Text JSON?

The System.Text.Json namespace contains all the entry points and the main types. The System.Text.Json.Serialization namespace contains attributes and APIs for advanced scenarios and customization specific to serialization and deserialization.


1 Answers

This is implemented in .Net 5.0:

Support ignoring value-type defaults

This version introduces JsonIgnoreCondition enum:

/// When specified on JsonSerializerOptions.DefaultIgnoreCondition,
/// determines when properties and fields across the type graph are ignored.
/// When specified on JsonIgnoreAttribute.Condition, controls whether
/// a property is ignored during serialization and deserialization. This option
/// overrides the setting on JsonSerializerOptions.DefaultIgnoreCondition.
public enum JsonIgnoreCondition
{
    /// Property is never ignored during serialization or deserialization.
    Never = 0,
    /// Property is always ignored during serialization and deserialization.
    Always = 1,
    /// If the value is the default, the property is ignored during serialization.
    /// This is applied to both reference and value-type properties and fields.
    WhenWritingDefault = 2,
    /// If the value is <see langword="null"/>, the property is ignored during serialization.
    /// This is applied only to reference-type properties and fields.
    WhenWritingNull = 3,
}

Specifically JsonIgnoreCondition.WhenWritingDefault will suppress false Boolean values. It may be applied in one of two ways. Firstly, you can apply it directly to a member using JsonIgnoreAttribute.Condition:

public class Model
{
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool Value { get; set; }
}

Demo fiddle #1 here.

Secondly, you may set it in JsonSerializerOptions.DefaultIgnoreCondition:

Specifies a condition to determine when properties with default values are ignored during serialization or deserialization. The default value is Never.

I.e. given the following model:

public class Model
{
    public bool Value { get; set; }
}

You may serialize it as follows to skip serialization of false values in runtime:

var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault };
var json = JsonSerializer.Serialize(model, options);

Demo fiddle #2 here.

Notes:

  1. The .Net 5.0 docs for JsonIgnoreCondition appear to have some inaccuracies. Firstly, they claim that WhenWritingDefault means that

    Property will only be ignored if it is null.

    However, in fact the property will be ignored if it is default as stated in the source code.

    Secondly, they claim that WhenWritingNull

    is applied only to reference-type properties and fields.

    However, testing shows that it applies to nullable value type members as well. E.g. given the model:

    public class Model
    {
        public bool? Value { get; set; }
    }
    

    Serializing with DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault omits Value when it it is null:

    var model = new Model(); // Leave value null
    
    var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault };
    Console.WriteLine(JsonSerializer.Serialize(model, options)); // Prints {}
    

    Demo fiddle #3 here.

  2. Setting JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault applies to all value types not just bool. Thus if you have any double, int, DateTime, decimal (including a zero-valued decimal with a specified number of digits such as decimal.Parse("0.0000")) or other value type members, they will be omitted when the value equals the default.

    There does not appear to be a way to globally skip serialization of only default bool valued members while still serializing other value-type members, which could be done in Json.NET via a custom contract resolver.

    Demo fiddle #4 here.

  3. In determining whether a member has a default value, the default value for the type of the value (i.e. default(T)) is used. Unlike Json.NET, DefaultValueAttribute is not taken into consideration.

    Demo fiddle #5 here.

  4. Prior to .Net 5.0 you would need to create a custom JsonConverter for the containing type (i.e. Model in the above examples) and manually skip or serialize each member as desired.

like image 148
dbc Avatar answered Oct 19 '22 11:10

dbc