.net 仅使用System.Text.Json忽略bool数据类型的默认值

o7jaxewo  于 2023-05-19  发布在  .NET
关注(0)|答案(2)|浏览(208)

在System.Text.json返回false时,是否有一种全局级别的方法可以忽略所有布尔值?
我知道有这个全局条件,但我仍然需要返回其他默认值。

JsonSerializerOptions options = new()
           {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
            };

理想情况下不想单独添加以下所有属性。[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]

1l5u6lss

1l5u6lss1#

你不能对所有类型都使用自定义的JsonConverter,因为那样你就必须重新发明轮子来序列化整个东西。你也不能使用JsonConverter<bool>(或<bool?>),因为你必须在它的Write()方法中写入一个值。
因此,使用自定义的Modifiers操作注册一个DefaultJsonTypeInfoResolver,该操作仅在布尔值等于true时序列化它们:

JsonSerializerOptions options = new()
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers =
        {
            jsonTypeInfo =>
            {
                foreach (var p in jsonTypeInfo.Properties)
                {
                    if (p.PropertyType == typeof(bool) || p.PropertyType == typeof(bool?))
                    {
                        p.ShouldSerialize = (containingObject, propertyValue) =>
                        {
                            return propertyValue as bool? == true;
                        };
                    }
                }
            }
        }
    }
};

MS Learn: Customize a JSON contract。自.NET 7起运行。

hujrc8aj

hujrc8aj2#

在**.NET 7及更高版本**中,您可以使用typeInfo modifier自定义类型的contract,以跳过值为false的bool属性的序列化。
首先定义以下修饰符:

public static partial class JsonExtensions
{
    static Func<object, object?, bool> ShouldSerializeBool { get; } = static (obj, value) => (value is bool b ? b : true);

    public static Action<JsonTypeInfo> IgnoreFalseBoolProperties { get; } = static typeInfo => 
        {
            if (typeInfo.Kind != JsonTypeInfoKind.Object)
                return;
            foreach (var property in typeInfo.Properties)
                if (property.PropertyType == typeof(bool))
                {
                    if (property.ShouldSerialize is {} shouldSerialize)
                        property.ShouldSerialize = (o, v) => ShouldSerializeBool(o, v) && shouldSerialize(o, v);
                    else
                        property.ShouldSerialize = ShouldSerializeBool;
                }
        };
}

现在,如果你的模型看起来像这样,例如:

public record Model(bool BoolValue, int IntValue, bool? NullableBoolValue);

使用修改器序列化具有默认值的模型时:

var options = new JsonSerializerOptions
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers = { JsonExtensions.IgnoreFalseBoolProperties },
    },
    // Others as required
};
var json = JsonSerializer.Serialize(new Model(default, default, default), options);

将跳过false bool属性:

{"IntValue":0,"NullableBoolValue":null}

但是当序列化为一个真正的bool值时:

var json2 = JsonSerializer.Serialize(new Model(true, default, default), options);

您将获得:

{"BoolValue":true,"IntValue":0,"NullableBoolValue":null}

演示小提琴here

相关问题