如何使用 System.Text.Json 忽略错误值

Posted

技术标签:

【中文标题】如何使用 System.Text.Json 忽略错误值【英文标题】:How to ignore false values with System.Text.Json 【发布时间】:2020-02-02 03:15:00 【问题描述】:

我正在我的 .NET Core 3.0 应用程序中从 Newtonsoft.Json 迁移到 System.Text.Json。我试图忽略错误值。

System.Text.Json 我找到了忽略空值的选项:

JsonSerializerOptions.IgnoreNullValues = true;

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

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

或者,如果有人知道相当于 Newtonsoft DefaultValueHandling = DefaultValueHandling.Ignore 的选项,那也太棒了。

【问题讨论】:

如果我理解你的正确,我认为你必须使用属性 [Default(false)]。 感谢@AndreasSchmidt 属性[DefaultValue(false)] 来自Newtonsoft.Json。我想使用System.Text.Json 我很确定它不是来自 Newtonsoft.Json:docs.microsoft.com/en-us/dotnet/api/… 抱歉你是对的@AndreasSchmidt!它实际上来自 System.ComponentModel 命名空间。不幸的是[DefaultValue(false)] 不起作用。 @dbc 不幸的是,这不是真的。你只负责写值,属性名已经写好了。所以如果你不写,你会得到一个无效的 JSON 【参考方案1】:

这是在.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; 

演示小提琴 #1 here.

其次,你可以设置在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);

演示小提琴#2 here.

注意事项:

    .Net 5.0 docs for JsonIgnoreCondition 似乎有一些不准确之处。首先,他们声称WhenWritingDefault 意味着

    只有null 的属性才会被忽略。

    然而,事实上,如果它是source code 中所述的default,则该属性将被忽略。

    其次,他们声称WhenWritingNull

    仅适用于引用类型的属性和字段。

    但是,测试表明它也适用于nullable 值类型成员。例如。给定模型:

    public class Model
    
        public bool? Value  get; set; 
    
    

    使用DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault 进行序列化时,Value 为 null:

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

    演示小提琴#3 here.

    设置JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault 适用于所有值类型,而不仅仅是bool。因此,如果您有任何doubleintDateTimedecimal(包括具有指定位数的零值小数,例如decimal.Parse("0.0000"))或其他值类型成员,它们将被省略该值等于默认值。

    似乎没有一种方法可以全局跳过仅默认 bool 值成员的序列化,同时仍序列化其他值类型成员,这可以通过自定义合约解析器在 Json.NET 中完成。

    演示小提琴 #4 here.

    在确定成员是否具有默认值时,使用值的类型的默认值(即default(T))。与Json.NET 不同,DefaultValueAttribute 不被考虑在内。

    演示小提琴 #5 here.

    在 .Net 5.0 之前,您需要为包含类型创建一个 custom JsonConverter(即上述示例中的 Model)并根据需要手动跳过或序列化每个成员。

【讨论】:

以上是关于如何使用 System.Text.Json 忽略错误值的主要内容,如果未能解决你的问题,请参考以下文章

.NET 6 中 System.Text.Json 的新特性

如何在反序列化之前使用 System.Text.Json 验证 JSON

如何在 System.Text.Json 中使用 JsonConstructor 属性

如何将类字段与 System.Text.Json.JsonSerializer 一起使用?

如何使用 JsonConverter 在 System.Text.Json.JsonSerializer.Serialize() 中排除属性被序列化

如何使用 System.Text.Json 处理可为空的引用类型?