dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.23k stars 4.45k forks source link

JsonSerializer allows nulls in arrays of non-nullable T #101659

Closed neon-sunset closed 2 weeks ago

neon-sunset commented 2 weeks ago

Description

It appears that System.Text.Json treats the following objects in the same way:

record Nullable(string?[] Names);
record NonNullable(string[] Names);

Reproduction Steps

using System.Text.Json;

var json = """
{
    "Names": ["Alice", "Bob", null, "Charlie"]
}
""";

var shouldSucceed = JsonSerializer.Deserialize<Nullable>(json);
var shouldFail = JsonSerializer.Deserialize<NonNullable>(json);

throw new Exception("Unreachable!");

record Nullable(string?[] Names);
record NonNullable(string[] Names);

Expected behavior

Serializer throws an exception

Actual behavior

The "unreachable" exception is thrown

Regression?

No

Known Workarounds

Using custom converter

Configuration

.NET 8.0.3

Other information

No response

dotnet-policy-service[bot] commented 2 weeks ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

huoyaoyuan commented 2 weeks ago

I believe this is covered under #100144.

neon-sunset commented 2 weeks ago

Ah, my bad, I tried searching for issues and could not find an appropriate one. Thanks.

eiriktsarpalis commented 2 weeks ago

Note that non-nullable element types are out of scope for https://github.com/dotnet/runtime/issues/100144, due to restrictions in their run-time representation.

neon-sunset commented 2 weeks ago

Note that non-nullable element types are out of scope for #100144, due to restrictions in their run-time representation.

I see. Could there be a possibility of that changing in the future? (perhaps for source-generated serialization only?)

eiriktsarpalis commented 1 week ago

Note that non-nullable element types are out of scope for #100144, due to restrictions in their run-time representation.

I see. Could there be a possibility of that changing in the future? (perhaps for source-generated serialization only?)

Unlikely. The serialization infrastructure is shared between reflection and source gen and both key they contracts on Type, which cannot distinguish between List<string> and List<string?>.