diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 4a91f0a4924ed..adfbe746acadc 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -141,6 +141,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af | Title | Type of change | |-------|-------------------| +| [System.Text.Json checks for property name conflicts](serialization/10/property-name-validation.md) | Behavioral change | | [XmlSerializer no longer ignores properties marked with ObsoleteAttribute](serialization/10/xmlserializer-obsolete-properties.md) | Behavioral change | ## Windows Forms diff --git a/docs/core/compatibility/serialization/10/property-name-validation.md b/docs/core/compatibility/serialization/10/property-name-validation.md new file mode 100644 index 0000000000000..204500dd2c68c --- /dev/null +++ b/docs/core/compatibility/serialization/10/property-name-validation.md @@ -0,0 +1,68 @@ +--- +title: "Breaking change: System.Text.Json checks for property name conflicts" +description: "Learn about the breaking change in .NET 10 where System.Text.Json validates that user-defined property names don't conflict with reserved metadata property names." +ms.date: 11/13/2025 +ai-usage: ai-assisted +--- +# System.Text.Json checks for property name conflicts + +Under certain contexts, such as polymorphism and reference preservation, reserves specific property names (for example, `$type`, `$id`, and `$ref`) for emitting metadata. Some property names such as the `TypeDiscriminatorPropertyName` can also be configured with custom names. Previously, the serializer didn't perform validation on whether these property names conflicted with user-defined contracts, which could result in duplicate properties and produce JSON that was ambiguous or failed to round-trip. Starting with .NET 10, System.Text.Json enables validation to prevent such configurations and provides early warning to users. + +## Version introduced + +.NET 10 + +## Previous behavior + +Previously, the following code produced an invalid JSON object with duplicate `Type` properties and failed to deserialize with a : + +```csharp +using System.Text.Json; +using System.Text.Json.Serialization; + +string json = JsonSerializer.Serialize(new Dog()); +Console.WriteLine(json); // {"Type":"dog","Type":"Dog"} +JsonSerializer.Deserialize(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"; +} +``` + +## New behavior + +Starting in .NET 10, any attempt to serialize that same type results 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. + +This validation error occurs when the serializer is first created or when serialization is first attempted, providing early detection of invalid serialization contracts. + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +This change provides early prevention of invalid serialization contracts. By validating property names upfront, the serializer prevents scenarios where duplicate properties would be emitted, resulting in invalid JSON that cannot round-trip correctly. This helps developers identify and fix configuration issues during development rather than discovering them at run time during deserialization. + +For more information, see: + +- [[STJ] Disallow property names that conflict with metadata property names (dotnet/runtime#106390)](https://github.com/dotnet/runtime/issues/106390) +- [Disallow types with property names conflicting with metadata (dotnet/runtime#106460)](https://github.com/dotnet/runtime/pull/106460) + +## Recommended action + +Avoid using property names that conflict with System.Text.Json-specific metadata properties (such as `$type`, `$id`, and `$ref`). If it's absolutely necessary to keep such a property in the class, apply a annotation on the conflicting property. + +## Affected APIs + +- +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 78a5d4adf5f58..aadc279515248 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -172,6 +172,8 @@ items: href: sdk/10.0/prune-packagereference-privateassets.md - name: Serialization items: + - name: System.Text.Json checks for property name conflicts + href: serialization/10/property-name-validation.md - name: XmlSerializer no longer ignores properties marked with ObsoleteAttribute href: serialization/10/xmlserializer-obsolete-properties.md - name: Windows Forms