为什么 .NET 的 System.Text.Json.JsonSerializer.Deserialize 方法的 return 类型可以为空,而 return 不为空?
Why are the return types of .NET's System.Text.Json.JsonSerializer.Deserialize methods nullable when it doesn't return null?
考虑 .NET 6 的 System.Text.Json.JsonSerializer.Deserialize 方法及其许多重载。
每个 return 都是 object?
或 TValue?
,这表明 null
可以被 return 编辑。但是,文档指出,如果出现任何错误,则会抛出异常。此外,它还声明一个有效值是 returned(如果没有抛出异常)。它没有在任何地方声明 null
可以被 returned。根据我的使用经验,null
永远不会被 returned.
(如果您在项目中打开“可空性”,那么可为空的 return 类型是一个问题,因为编译器随后会开始警告您 returned 值 可能为 null - 根据我的经验(根据文档)这不是真的。正是这种事情让我急于再次关闭可空性。我知道我可以抑制警告,但我不要认为那是重点。)
是否缺少文档?这些方法真的可以 return null 吗?如果他们不能,那为什么我们有可为空的 return 类型?
根据 RFC 7159,“null”(以及“true”和“false”)将是有效的 JSON 文本。但是,空字符串不是有效的 JSON.
TValue? Deserialize<TValue>
只是 Object? Deserialize(type: typeof(TValue))
. 的包装
- 当
#nullable
注释被添加到 C# 8.0 时,System.Type
类型未扩展以支持这些注释。
- 因此,C# 中的 generic-type 不可能知道(在运行时)generic-type 参数的具体 type-argument 是 nullable-reference-type 还是非nullable-reference-type。
- (这当然不适用于
Nullable<T>
)
- 更新:In .NET 6 it is now possible to use runtime reflection to inspect nullable annotations with
NullabilityInfoContext
.
- 因此,在运行时,使用
TValue := MyClass?
或 TValue := MyClass
的 Deserialize<TValue>()
的 call-site 将表现相同,因为 Deserialize
方法不知道是否MyClass
是否有 ?
注释。
Deserialize<TValue>
方法只知道 TValue
是否是 reference-type(通过 typeof(TValue)
)。
- 因此,如果您指示
JsonSerializer
反序列化字符串 "null"
( 有效 JSON) 并且 如果 TValue
是引用类型,那么它将 return null
。
- ...即使 你的
TValue
没有 ?
。请记住 JsonSerializer
不知道(也不能)知道!
- 这就是方法的静态 return-type 具有
?
注释的原因,因为如果它没有,那么它将错误地断言它永远不会 returns null
.
可以说 JsonSerialize
的设计者 可以 添加更多允许调用者静态断言的方法 non-null-ness,但他们没有t,但如果你真的想,你可以:
像这样:
public static TValue DeserializeNonNullObject<TValue>( String json )
where TValue : class
{
TValue? orNull = JsonSerializer.Deserialize<TValue>( json );
return orNull ?? throw new JsonException( "Expected deserialized object to be non-null, but encountered null." );
}
考虑 .NET 6 的 System.Text.Json.JsonSerializer.Deserialize 方法及其许多重载。
每个 return 都是 object?
或 TValue?
,这表明 null
可以被 return 编辑。但是,文档指出,如果出现任何错误,则会抛出异常。此外,它还声明一个有效值是 returned(如果没有抛出异常)。它没有在任何地方声明 null
可以被 returned。根据我的使用经验,null
永远不会被 returned.
(如果您在项目中打开“可空性”,那么可为空的 return 类型是一个问题,因为编译器随后会开始警告您 returned 值 可能为 null - 根据我的经验(根据文档)这不是真的。正是这种事情让我急于再次关闭可空性。我知道我可以抑制警告,但我不要认为那是重点。)
是否缺少文档?这些方法真的可以 return null 吗?如果他们不能,那为什么我们有可为空的 return 类型?
根据 RFC 7159,“null”(以及“true”和“false”)将是有效的 JSON 文本。但是,空字符串不是有效的 JSON.
TValue? Deserialize<TValue>
只是Object? Deserialize(type: typeof(TValue))
. 的包装
- 当
#nullable
注释被添加到 C# 8.0 时,System.Type
类型未扩展以支持这些注释。- 因此,C# 中的 generic-type 不可能知道(在运行时)generic-type 参数的具体 type-argument 是 nullable-reference-type 还是非nullable-reference-type。
- (这当然不适用于
Nullable<T>
)
- (这当然不适用于
- 更新:In .NET 6 it is now possible to use runtime reflection to inspect nullable annotations with
NullabilityInfoContext
.
- 因此,C# 中的 generic-type 不可能知道(在运行时)generic-type 参数的具体 type-argument 是 nullable-reference-type 还是非nullable-reference-type。
- 因此,在运行时,使用
TValue := MyClass?
或TValue := MyClass
的Deserialize<TValue>()
的 call-site 将表现相同,因为Deserialize
方法不知道是否MyClass
是否有?
注释。Deserialize<TValue>
方法只知道TValue
是否是 reference-type(通过typeof(TValue)
)。
- 因此,如果您指示
JsonSerializer
反序列化字符串"null"
( 有效 JSON) 并且 如果TValue
是引用类型,那么它将 returnnull
。- ...即使 你的
TValue
没有?
。请记住JsonSerializer
不知道(也不能)知道!
- ...即使 你的
- 这就是方法的静态 return-type 具有
?
注释的原因,因为如果它没有,那么它将错误地断言它永远不会 returnsnull
.
可以说 JsonSerialize
的设计者 可以 添加更多允许调用者静态断言的方法 non-null-ness,但他们没有t,但如果你真的想,你可以:
像这样:
public static TValue DeserializeNonNullObject<TValue>( String json )
where TValue : class
{
TValue? orNull = JsonSerializer.Deserialize<TValue>( json );
return orNull ?? throw new JsonException( "Expected deserialized object to be non-null, but encountered null." );
}