-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
Description
Under certain contexts (polymorphism, reference preservation) System.Text.Json reserves specific property names that it uses to emit metadata over the wire: $type, $id, $ref, etc. It does so however without performing any validation on whether these property names conflict with user-defined contracts. In such situations, STJ would emit duplicate properties and produce JSON that is ambiguous or fails to roundtrip. Starting with .NET 10, STJ enables validation preventing such configurations, giving early warning to users.
Version
.NET 10
Previous behavior
The following code:
using System.Text.Json;
using System.Text.Json.Serialization;
string json = JsonSerializer.Serialize<Animal>(new Dog());
Console.WriteLine(json); // {"Type":"dog","Type":"Dog"}
JsonSerializer.Deserialize<Animal>(json); // JsonException: Deserialized object contains a duplicate 'Type' metadata property.
[JsonPolymorphic(TypeDiscriminatorPropertyName = "Type")]
[JsonDerivedType(typeof(Dog), "dog")]
public abstract class Animal
{
public abstract string Type { get; }
}
public class Dog : Animal
{
public override string Type => "Dog";
}Will produce an invalid JSON object and fail to deserialize with a deserialization exception
New behavior
Starting with .NET 10 any attempt to serialize that same type will result in an early validation error:
InvalidOperationException: The type 'Dog' contains property 'Type' that conflicts with an existing metadata property name. Consider either renaming it or ignoring it with JsonIgnoreAttribute
Type of breaking change
- Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
- Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
- Behavioral change: Existing binaries might behave differently at run time.
Reason for change
Provides early prevention of invalid serialization contracts. See the original issue of [STJ] Disallow property names that conflict with metadata property names (dotnet/runtime#106390) and the pull request to Disallow types with property names conflicting with metadata. (dotnet/runtime#106460) for more information.
Recommended action
Users should avoid using property names that conflict with STJ specific metadata. If absolutely necessary to keep such a property around, a JsonIgnore annotation should be applied on the conflicting property.
Feature area
Serialization
Affected APIs
No response
Metadata
Metadata
Labels
Type
Projects
Status