作者:手机用户2502938137 | 来源:互联网 | 2023-09-01 16:28
c#
在 .Net Core 3.1 和使用System.Text.Json
库中,我遇到了 Newtonsoft 库中没有出现的问题。
如果我在 JSON 中为某些类型(后端类型)DateTime?
或 的属性发送一个空字符串int?
,它会返回 400 状态代码,并带有一条错误消息,表示值无法反序列化。但是,对于 Newtonsoft,空字符串会自动解释为任何值的空值。Nullable.
一个最小的例子是:
var json = """";
Assert.AreEqual(null, Newtonsoft.Json.JsonConvert.DeserializeObject(json)); // Passes
Assert.AreEqual(null, System.Text.Json.JsonSerializer.Deserialize(json)); // Throws System.Text.Json.JsonException: The JSON value could not be converted to System.Nullable`1[System.DateTime].
有没有办法让System.Text.Json
行为以同样的方式?演示在这里。
回答
您可以使用工厂转换器模式来创建一个JsonConverterFactory
导致空字符串被解释null
为所有Nullable
类型值的。
以下工厂完成这项工作:
public class NullableConverterFactory : JsonConverterFactory
{
static readonly byte [] Empty = Array.Empty();
public override bool CanConvert(Type typeToConvert) => Nullable.GetUnderlyingType(typeToConvert) != null;
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) =>
(JsonConverter)Activator.CreateInstance(
typeof(NullableConverter<>).MakeGenericType(
new Type[] { Nullable.GetUnderlyingType(type) }),
BindingFlags.Instance | BindingFlags.Public,
binder: null,
args: new object[] { options },
culture: null);
class NullableConverter : JsonConverter where T : struct
{
// DO NOT CACHE the return of (JsonConverter)options.GetConverter(typeof(T)) as DoubleConverter.Read() and DoubleConverter.Write()
// DO NOT WORK for nondefault values of JsonSerializerOptions.NumberHandling which was introduced in .NET 5
public NullableConverter(JsonSerializerOptions options) {}
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
if (reader.ValueTextEquals(Empty))
return null;
}
return JsonSerializer.Deserialize(ref reader, options);
}
public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, value.Value, options);
}
}
该工厂应添加到JsonSerializerOptions.Converters
您的框架集合中。
笔记:
- 在这个答案的原始版本中,我缓存了
(JsonConverter)options.GetConverter(typeof(T))
Microsoft 推荐的性能回报。不幸的是在所指出的评论通过曲折微软自己DoubleConverter.Read()
和DoubleConverter.Write()
方法,不占非缺省值JsonSerializerOptions.NumberHandling
,所以我已删除了该逻辑.NET 5。
演示小提琴在这里。