System.Text.Json.JsonSerializer.Deserialize() 的 .net 5.0 签名更改

.net 5.0 signature change of System.Text.Json.JsonSerializer.Deserialize()

我正在尝试从 .NET Core 3.1 到 .NET 5.0 的步骤,并在使用 Deserialize<TValue>(String, JsonSerializerOptions) 时收到一堆可空性警告。快速调查显示签名已从

public static TValue Deserialize<TValue> (string json, System.Text.Json.JsonSerializerOptions options = default); (doc) 在 .NET Core 3.1 到

public static TValue? Deserialize<TValue> (string json, System.Text.Json.JsonSerializerOptions? options = default); (doc) 在 .NET 5.0 中。

它看起来是一个合理的更改,但我无法引发空值以实际被 returned,因为所有不良的 input/bad 使用都会在我的实验中抛出异常,据我所知,文档没有描述为什么调用 return 为 null。

似乎没有必要向我们所有的用途添加 null return 检查,如果失败的反序列化将抛出而不是 returning null。

我错过了什么?

original JSON proposal 所示,文本 null 的格式完全正确 JSON:

A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.

这一点在 RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format 中得到了进一步阐明,其中指出格式良好的 JSON 文本只需包含一个原始值,包括 null:

A JSON text is a sequence of tokens. The set of tokens includes six structural characters, strings, numbers, and three literal names [false, true and null].

A JSON text is a serialized value. Note that certain previous specifications of JSON constrained a JSON text to be an object or an array. Implementations that generate only objects or arrays where a JSON text is called for will be interoperable in the sense that all implementations will accept these as conforming JSON texts.

根据最新的 JSON RFC,由于 null 是一个格式良好的 JSON 文本,因此 JsonSerializer 在将其反序列化为引用类型时不会抛出或可为 null 的值类型,并且只会 return 空值:

object? obj1 = JsonSerializer.Deserialize<object>("null"); // Does not throw; explicitly typed for clarity.
Assert.IsNull(obj1);     // Passes
var array = JsonSerializer.Deserialize<int []>("null");    // Does not throw;
Assert.IsNull(array);    // Passes
var nullable = JsonSerializer.Deserialize<int?>("null");   // Does not throw;
Assert.IsNull(nullable); // Passes

相反,以下生成编译器警告:

#nullable enable
object obj2 = JsonSerializer.Deserialize<object>("null"); // Compiler warning: Converting null literal or possible value to non-nullable type;

并且以下抛出,因为 int 是不可为 null 的值类型,null 不能 分配给它:

var i = JsonSerializer.Deserialize<int>("null");  // Throws, since int is a non-nullable value type.

如果你想在反序列化 JSON 文本 null 时抛出异常,你可以添加以下扩展方法:

public static class ObjectExtensions
{
    public static T ThrowOnNull<T>(this T? value) where T : class => value ?? throw new ArgumentNullException();
}

然后做:

var value = JsonSerializer.Deserialize<TValue>(json).ThrowOnNull();

演示 fiddle here.