如何使用 System.Text.Json 忽略 false 值

12

我正在将我的.NET Core 3.0应用程序从Newtonsoft.Json迁移到System.Text.Json。我想忽略false值。

System.Text.Json中,我找到了忽略null值的选项:

JsonSerializerOptions.IgnoreNullValues = true;

但我找不到在System.Text.Json中忽略false值的选项。

有人知道如何使用System.Text.Json实现这一点吗?

或者如果有人知道Newtonsoft DefaultValueHandling = DefaultValueHandling.Ignore选项的等效方法,那就太棒了。


1
我非常确定它不是来自Newtonsoft.Json:https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.defaultvalueattribute?view=netframework-4.8 - Andreas Schmidt
在反序列化时,您需要忽略具有默认值的属性,对吗? - Andreas Schmidt
正确。我想忽略值为“false”的属性。 - stevo
似乎目前还没有实现。JsonSerializer.Write.HandleObject.cs 是写入对象属性的地方。其中有一个检查 jsonPropertyInfo.IgnoreNullValuesjsonPropertyInfo.ShouldSerialize 的操作,但没有检查默认值,也没有检查自定义的 ShouldSerializeXXX() 方法。 - dbc
1
@dbc 不幸的是,那不是真的。你只负责写入值,属性名称已经写好了。所以如果你不写它,你会得到一个无效的JSON。 - Thomas Levesque
显示剩余6条评论
1个回答

17

这是在.Net 5.0中实现的:

支持忽略值类型默认值

此版本引入了JsonIgnoreCondition枚举:

/// 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,
}
具体来说,JsonIgnoreCondition.WhenWritingDefault将抑制false布尔值。它可以通过以下两种方式之一应用。首先,您可以直接使用JsonIgnoreAttribute.Condition应用于成员:
public class Model
{
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool Value { get; set; }
}

这里是演示fiddle #1 链接

其次,您可以在JsonSerializerOptions.DefaultIgnoreCondition中设置它:

指定一个条件来确定何时在序列化或反序列化期间忽略具有默认值的属性。默认值为Never

例如,给定以下模型:

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

为了在运行时跳过false值的序列化,您可以按以下方式进行序列化:

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

这里是演示fiddle #2 链接

注:

  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.


这个关于System.Text.Json序列化的页面涵盖了JsonSerializerOptions的含义。请访问:https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/ignore-properties?pivots=dotnet-7-0#ignore-individual-properties - Jonathan Tyson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接