Consider .NET 6's System.Text.Json.JsonSerializer.Deserialize method and its many overloads.
Each one returns either object?
or TValue?
which indicates that null
could be returned. However, the documentation states that in the event of any error, an exception is thrown. Moreover, it also states that a valid value is returned (if an exception isn't thrown). Nowhere does it state that null
could be returned. And in my experience of using it, null
is never returned.
(The nullable return type is a problem if you turn on "nullability" in your project, because the compiler then starts warning you that the returned value could be null - which in my experience (and according to the documentation) just isn't true. It's this sort of thing that has me scurrying to switch nullability off again. I know I can suppress the warning, but I don't think that's the point.)
Is the documentation lacking? Can the methods really return null? If they can't, then why do we have nullable return types?
CodePudding user response:
TValue? Deserialize<TValue>
is just a wrapper forObject? Deserialize(Type)
.- When
#nullable
annotations were added to C# 8.0, theSystem.Type
type was not extended with support for those annotations.- Therefore, it is not possible for a generic-type in C# to know (at runtime) if a generic-type-parameter's concrete type-argument is a nullable-reference-type or a non-nullable-reference-type.
- (This doesn't apply to
Nullable<T>
, of course)
- (This doesn't apply to
- Therefore, it is not possible for a generic-type in C# to know (at runtime) if a generic-type-parameter's concrete type-argument is a nullable-reference-type or a non-nullable-reference-type.
- So, at runtime, a call-site for
Deserialize<TValue>()
using eitherTValue := MyClass?
orTValue := MyClass
will behave identically because theDeserialize
method has no idea ifMyClass
has the?
annotation or not.- The
Deserialize<TValue>
method only knows ifTValue
is a reference-type or not (viatypeof(TValue)
).
- The
- Therefore, if you instruct
JsonSerializer
to deserialize the string"null"
(which is valid JSON) and ifTValue
is a reference type, then it will returnnull
. - Which is why the method's static return-type has the
?
annotation.
It can be argued that JsonSerialize
's designers could have added some more methods that allowed callers to statically assert non-null-ness, but they didn't, but you can if you really want to:
Like so:
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." );
}
CodePudding user response:
According to RFC 7159 “null” (and “true” and “false”) will be valid JSON text. However, empty string is not a valid JSON.