Closed Septercius closed 8 months ago
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.
Author: | Septercius |
---|---|
Assignees: | - |
Labels: | `area-System.Text.Json`, `untriaged` |
Milestone: | - |
I'm seeing a couple of issues:
KeyCollection<int, TValue>
types, since it duck types on the indexer signature to generate an List-like serialization loop in the fast-path serializer. We might want to consider adding a check particularly for that corner case.Minimal reproduction:
var value = new MyKeyedCollection { 1, 2, 3 };
JsonSerializer.Serialize(value, MyContext.Default.MyKeyedCollection);
[JsonSerializable(typeof(MyKeyedCollection))]
internal partial class MyContext : JsonSerializerContext;
public class MyKeyedCollection : KeyedCollection<int, int>
{
protected override int GetKeyForItem(int k) => k;
}
A simple workaround for that issue is to disable fast-path generation for that particular type:
var value = new MyKeyedCollection { 1, 2, 3 };
var result = JsonSerializer.Serialize(value, MyContext.Default.MyKeyedCollection);
JsonSerializer.Deserialize(result, MyContext.Default.MyKeyedCollection);
[JsonSerializable(typeof(MyKeyedCollection), GenerationMode = JsonSourceGenerationMode.Metadata)]
internal partial class MyContext : JsonSerializerContext;
Description
I'm trying to use the source generation capabilities of System.Text.Json to serialize and deserialize a type that contains an instance of the
KeyedCollection<,>
class. The documentation (https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/supported-collection-types) states that this is not a fully supported type (specifically, non-string key types), but it does appear to work without problem when not using source generation (so long as I useJsonObjectCreationHandling.Populate
), and I get the expected results.I then tried using the source generation using the same object, and this is failing with a "The given key '0' was not present in the dictionary" error. Looking at the generated code, it's iterating through the collection using a standard for loop, and accessing the items in the collection by index, which doesn't work with
KeyedCollection<,>
as the indexer requires a key.Deserializing using source generation does seem to work (it doesn't throw an exception).
A few questions:
KeyedCollection<,>
actually supported when not using source generation (contrary to what the documentation states)?foreach
instead?Reproduction Steps
Paste the following into a new project:
Expected behavior
The object is successfully serialized to JSON.
Actual behavior
The code throws an exception: "The given key '0' was not present in the dictionary".
Regression?
No response
Known Workarounds
No response
Configuration
.NET 8, Mac OS Ventura 13.6.4, x86_64
Other information
The code generating the source appears to be the
GenerateFastPathFuncForEnumerable
method: https://github.com/dotnet/runtime/blob/7a60900cd1be3361773237d0d0d0293146db5547/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs#L406