Description
Description
Deserializing JSON with preserved references throws an exception if any dictionary keys begin with an escaped '$' character.
Reproduction Steps
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode;
public record TestRecord{
public Dictionary<string, string> TestDict {get; init;} = new();
}
public class Program
{
public static void Main()
{
TestRecord test = new () {
TestDict = new(){
["$break"] = "broken"
}
};
TextEncoderSettings encoderSettings = new();
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
encoderSettings.ForbidCharacter('$');
JsonSerializerOptions options = new(){ReferenceHandler = ReferenceHandler.Preserve, Encoder = JavaScriptEncoder.Create(encoderSettings)};
string json = JsonSerializer.Serialize(test, options);
TestRecord deserialized = JsonSerializer.Deserialize<TestRecord>(json, options);
}
}
Expected behavior
The exception should only be thrown if a key begins with an unescaped '$' character.
Actual behavior
The repro steps below compile and execute in dotnet 8 without exception, in dotnet 9 the following exception is thrown:
System.Text.Json.JsonException: Properties that start with '$' are not allowed in types that support metadata. Either escape the character or disable reference preservation and polymorphic deserialization.
Regression?
This worked prior to dotnet 9. It is not a documented breaking change in https://learn.microsoft.com/en-us/dotnet/core/compatibility/9.0
Known Workarounds
Setting AllowOutOfOrderMetadataProperties
to true will skip deserialization of the value. This is not a viable workaround for me.
Configuration
No response
Other information
No response