首先,你可能需要了解System.Text.Json
中一个特别的设计:JSON中的null
在运行时会被表示为.NET的null
。
例如:
var json = "null";
var node = JsonNode.Parse(json);
Console.WriteLine(node is null); // 输出 True
明白了这一点,编译器的警告就会更加合理,同时帮助你决定何时使用null原谅操作符。
现在看看你的代码:
JsonNode node = nodeNullable ?? throw new Exception("null JSON value");
虽然这解决了编译器警告,但在运行时可能合理也可能不合理。如果输入像上面的例子那样是null
怎么办?因此,你可以相应地调整这行代码:
- 如果你的代码绝不期望
node
为null
,你可以抛出异常
- 如果你的输入绝不会是
null
,你可以使用!
来原谅它
例如:
JsonNode node = JsonNode.Parse(jsonString)!;
记住,可空引用只是一个编译时的概念,在运行时没有意义。作为代码编写者,你比静态代码分析工具更了解输入情况。话虽如此,如果你决定原谅编译器的警告,而在运行时确实遇到了null
,将会抛出NullReferenceException
。
同样的理论也适用于你的另一行代码:
JsonNode? determinantNodeNullable = node["determinant"];
假设在这个上下文中,node
是一个JsonObject
(由Parse
方法返回)。JsonObject
本质上是Dictionary<string, JsonNode>
的一种变体。当你执行node["determinant"]
时,它会在内部存储中查找属性节点,如果找不到或者节点值为null
,node["determinant"]
将返回null
。
var json = "{\"prop\": null}";
var node = JsonNode.Parse(json)!;
var prop1 = node["foo"];
var prop2 = node["prop"];
// 两者都输出 True
Console.WriteLine(prop1 is null);
Console.WriteLine(prop2 is null);