我正在尝试从。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();
在这里演示小提琴