.net 5.0对System.Text.Json.JsonSerializer.Deserialize()的签名进行了



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

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

public static TValue? Deserialize<TValue> (string json, System.Text.Json.JsonSerializerOptions? options = default);(doc) in . net 5.0.

这看起来是一个合理的改变,但我还没有能够激发一个null实际返回,因为所有错误的输入/错误的使用将抛出一个异常在我的实验中,文档没有描述为什么调用将返回一个null据我所知。

似乎没有必要在所有使用中添加null返回检查,如果失败,反序列化将抛出而不是返回null。

我错过了什么?

如原始JSON提案所示,文本null是完全格式良好的JSON:

值可以是带双引号的字符串、数字、true、false或null,或对象或数组。这些结构可以嵌套。

这在RFC 8259中得到了进一步的澄清:JavaScript对象符号(JSON)数据交换格式,它指出一个格式良好的JSON文本只需要一个原始值,包括null:

JSON文本是一个令牌序列。标记集包括六个结构字符、字符串、数字和三个文字名称[false、true和null]。

JSON文本是一个序列化的值。请注意,以前的某些JSON规范将JSON文本约束为对象或数组。只生成需要JSON文本的对象或数组的实现将是可互操作的,因为所有实现都将接受这些作为符合JSON文本的实现。

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

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不能分配:
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();

在这里演示小提琴

相关内容

最新更新