英文:
Using System.Text.Json to ignore default values for bool data type, only
问题
是否有一种在全局级别忽略所有布尔类型并在返回false时使用System.Text.Json的方法?
我知道有这个全局条件,但我仍然需要返回其他默认值。
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
};
理想情况下,不想单独对所有属性添加以下内容..
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
英文:
Is there a way at a global level to ignore all and only bools when returning false with System.Text.Json?
I know there's this global condition, but I still need other default values to return.
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
};
Ideally would not like to add the following to all propeties individually..
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
答案1
得分: 2
以下是翻译好的部分:
无法为所有类型使用自定义 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 以后的版本。
英文:
You can't use a custom JsonConverter for all types, because then you'll have to reinvent the wheel to serialize whole thing. You also can't use a JsonConverter<bool>
(or <bool?>
), because you have to write a value in its Write()
method.
So register a DefaultJsonTypeInfoResolver
with a custom Modifiers
action that only serializes bools when their value equals 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;
};
}
}
}
}
}
};
From MS Learn: Customize a JSON contract. Works since .NET 7.
答案2
得分: 2
在 .NET 7及以后,你可以使用 typeInfo 修饰符 来定制你的类型的 合同,以跳过将值为 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 },
},
// 其他如有需要
};
var json = JsonSerializer.Serialize(new Model(default, default, default), options);
bool
属性为 false 的部分将会被跳过:
{"IntValue":0,"NullableBoolValue":null}
但当带有 true bool
值进行序列化时:
var json2 = JsonSerializer.Serialize(new Model(true, default, default), options);
你将得到:
{"BoolValue":true,"IntValue":0,"NullableBoolValue":null}
演示代码可以在 这里 查看。
英文:
In .NET 7 and later you can use a typeInfo modifier to customize your type's contract to skip serialization of bool
properties whose value is false.
First define the following modifier:
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;
}
};
}
And now if your model looks like, e.g.:
public record Model(bool BoolValue, int IntValue, bool? NullableBoolValue);
When you serialize a model with default values using the modifier:
var options = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { JsonExtensions.IgnoreFalseBoolProperties },
},
// Others as required
};
var json = JsonSerializer.Serialize(new Model(default, default, default), options);
The false bool
property will be skipped:
{"IntValue":0,"NullableBoolValue":null}
But when serialized with a true bool
value:
var json2 = JsonSerializer.Serialize(new Model(true, default, default), options);
You will get:
{"BoolValue":true,"IntValue":0,"NullableBoolValue":null}
Demo fiddle here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论