Skip to content

JsonSerializer.Deserialize fails to deserialize to {ReadOnly}Memory<T> #121267

@rampaa

Description

@rampaa

Description

When trying to deserialize a JSON to {ReadOnly}Memory<T>, JsonSerializer.Deserialize fails for some perfectly valid JSON files.

The following code prints Deserialization failed miserably!:

        using FileStream fileStream = File.OpenRead("Names.json");
        ReadOnlyMemory<NameRecord> nameRecords = JsonSerializer.Deserialize<ReadOnlyMemory<NameRecord>>(fileStream);
        if (nameRecords.Length is 0)
        {
            Console.WriteLine("Deserialization failed miserably!");
        }
        else
        {
            Console.WriteLine("Deserialization succeeded!");
        }

While the following code prints Deserialization succeeded!:

        using FileStream fileStream = File.OpenRead("Names.json");
        ReadOnlyMemory<NameRecord> nameRecords = JsonSerializer.Deserialize<NameRecord[]>(fileStream);
        if (nameRecords.Length is 0)
        {
            Console.WriteLine("Deserialization failed miserably!");
        }
        else
        {
            Console.WriteLine("Deserialization succeeded!");
        }

Potentially related to #118346


Should we just not use {ReadOnly}Memory as a deserialization target? Is its usage some kind of an edge case that is not well tested? I was under the impression that if I don't strictly need a List<T> or T[], deserializing a JSON file to ReadOnlyMemory<T> would have some performance benefits (like allocating less) but it causing all these issues for random JSON files makes me wonder whether I am missing a memo where its usage is discouraged for JSON deserialization.

Reproduction Steps

  1. Run ReadOnlyMemoryDeserializationBug.zip
  2. Notice it prints Deserialization failed miserably!
  3. Change JsonSerializer.Deserialize<ReadOnlyMemory<NameRecord>>(fileStream) to JsonSerializer.Deserialize<NameRecord[]>(fileStream) and re-run it.
  4. Notice it prints Deserialization succeeded!

Expected behavior

JsonSerializer.Deserialize<ReadOnlyMemory<T>> should be able to deserialize everything JsonSerializer.Deserialize<T[]> can deserialize.

Actual behavior

JsonSerializer.Deserialize<ReadOnlyMemory<T>> fails to deserialize some JSON files that JsonSerializer.Deserialize<T[]> deserializes just fine.

Regression?

Partially. For some JSON files .NET 8 does not fail but .NET 9 fails. For some other JSON files .NET 8 fails with an (incorrect) exception but .NET 9 fails silently. The attached repro project showcases where both .NET versions fail.

Known Workarounds

Deserializing to List<T> or T[] works fine

Configuration

Which version of .NET is the code running on?

.NET 9

What OS and version, and what distro if applicable?

Windows 10 22H2

What is the architecture (x64, x86, ARM, ARM64)?

x64

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions