Skip to content

Commit d864442

Browse files
Cam Sopergewarren
andauthored
Breaking change - System.Text.Json (#44946)
* Fixes 44172 * build fix * 44172 * lint * Build * whoops * titles * whoops * Feedback * wip * formatting * lint * toc and misc * path * review feedback * Apply suggestions from code review Co-authored-by: Genevieve Warren <[email protected]> --------- Co-authored-by: Genevieve Warren <[email protected]>
1 parent d25285a commit d864442

File tree

5 files changed

+78
-6
lines changed

5 files changed

+78
-6
lines changed

docs/core/compatibility/9.0.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@ If you're migrating an app to .NET 9, the breaking changes listed here might aff
112112

113113
## Serialization
114114

115-
| Title | Type of change | Introduced version |
116-
|-------------------------------------------------------------------------------|-------------------|--------------------|
117-
| [BinaryFormatter always throws](serialization/9.0/binaryformatter-removal.md) | Behavioral change | Preview 6 |
118-
| [Nullable JsonDocument properties deserialize to JsonValueKind.Null](serialization/9.0/jsondocument-props.md) | Behavioral change | Preview 1 |
115+
| Title | Type of change | Introduced version |
116+
|---------------------------------------------------------------------------------------------------------------------|-------------------|--------------------|
117+
| [BinaryFormatter always throws](serialization/9.0/binaryformatter-removal.md) | Behavioral change | Preview 6 |
118+
| [Nullable JsonDocument properties deserialize to JsonValueKind.Null](serialization/9.0/jsondocument-props.md) | Behavioral change | Preview 1 |
119+
| [System.Text.Json metadata reader now unescapes metadata property names](serialization/9.0/json-metadata-reader.md) | Behavioral change | GA |
119120

120121
## Windows Forms
121122

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: "Breaking change: System.Text.Json metadata reader now unescapes metadata property names"
3+
description: System.Text.Json now unescapes metadata property names, affecting reference preservation and metadata property validation.
4+
ms.date: 2/13/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/dotnet/docs/issues/44748
7+
---
8+
9+
# System.Text.Json metadata reader now unescapes metadata property names
10+
11+
The <xref:System.Text.Json?displayProperty=fullName> library has been updated to unescape metadata property names. This change affects how JSON documents are interpreted in the context of reference preservation, polymorphism, and metadata property validation.
12+
13+
## Version introduced
14+
15+
.NET 9
16+
17+
## Previous behavior
18+
19+
Previously, <xref:System.Text.Json?displayProperty=fullName> didn't unescape metadata property names. This would lead to invalid property names being accepted, which could bypass metadata property validation.
20+
21+
For example, the following code would succeed in the first call but throw an exception in the second call:
22+
23+
```csharp
24+
JsonSerializerOptions options = new() { ReferenceHandler = ReferenceHandler.Preserve };
25+
JsonSerializer.Deserialize<MyPoco>("""{"\u0024invalid" : 42 }""", options);
26+
JsonSerializer.Deserialize<MyPoco>("""{"$invalid" : 42 }""", options);
27+
28+
record MyPoco;
29+
```
30+
31+
The unescaping behavior could also cause polymorphism issues when roundtripping metadata properties whose names require escaping, as seen here:
32+
33+
```csharp
34+
string json = JsonSerializer.Serialize<Base>(new Derived());
35+
Console.WriteLine(json); // {"categor\u00EDa":"derived"}
36+
Console.WriteLine(JsonSerializer.Deserialize<Base>(json) is Derived); // False
37+
38+
[JsonPolymorphic(TypeDiscriminatorPropertyName = "categoría")]
39+
[JsonDerivedType(typeof(Derived), "derived")]
40+
public record Base;
41+
public record Derived : Base;
42+
```
43+
44+
## New behavior
45+
46+
<xref:System.Text.Json?displayProperty=fullName> now unescapes metadata property names. This new behavior means that the line `Console.WriteLine(JsonSerializer.Deserialize<Base>(json) is Derived);` from the polymorphic deserialization example now returns `true`, and that invalid property names correctly fail to deserialize with the following exception:
47+
48+
```output
49+
Unhandled exception. System.Text.Json.JsonException: Properties that start with '$' are not allowed in types that support metadata.
50+
```
51+
52+
## Type of breaking change
53+
54+
This change is a [behavioral change](../../categories.md#behavioral-change).
55+
56+
## Reason for change
57+
58+
The change improves correctness and reliability by ensuring that metadata property names are properly unescaped, preventing the bypass of metadata property validation. For more details, see the [reported issue](https://github.com/dotnet/runtime/issues/112288).
59+
60+
## Recommended action
61+
62+
Avoid using escaping to bypass metadata property validation. Instead, pick property names that don't conflict with metadata properties.
63+
64+
## Affected APIs
65+
66+
* <xref:System.Text.Json?displayProperty=fullName>
67+
* <xref:System.Text.Json.JsonSerializer.Deserialize*?displayProperty=fullName>

docs/core/compatibility/serialization/9.0/jsondocument-props.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "Nullable JsonDocument properties deserialize to JsonValueKind.Null"
2+
title: "Breaking change: Nullable JsonDocument properties deserialize to JsonValueKind.Null"
33
description: Learn about the breaking change in serialization in .NET 9 where nullable JsonDocument values deserialize to JsonValueKind.Null instead of null.
44
ms.date: 12/5/2024
55
ai-usage: ai-assisted

docs/core/compatibility/toc.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ items:
166166
href: serialization/9.0/binaryformatter-removal.md
167167
- name: Nullable JsonDocument properties deserialize to JsonValueKind.Null
168168
href: serialization/9.0/jsondocument-props.md
169+
- name: System.Text.Json metadata reader now unescapes metadata property names
170+
href: serialization/9.0/json-metadata-reader.md
169171
- name: Windows Forms
170172
items:
171173
- name: BindingSource.SortDescriptions doesn't return null
@@ -2022,6 +2024,8 @@ items:
20222024
href: serialization/9.0/binaryformatter-removal.md
20232025
- name: Nullable JsonDocument properties deserialize to JsonValueKind.Null
20242026
href: serialization/9.0/jsondocument-props.md
2027+
- name: System.Text.Json metadata reader now unescapes metadata property names
2028+
href: serialization/9.0/json-metadata-reader.md
20252029
- name: .NET 8
20262030
items:
20272031
- name: BinaryFormatter disabled for most projects

docs/core/compatibility/windows-forms/9.0/statusstrip-renderer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The previous default behavior didn't meet accessibility standards. The focus ind
3232
The new behavior is recommended for accessibility reasons. If you want to revert to the previous behavior, set the `RenderMode` property to <xref:System.Windows.Forms.ToolStripRenderMode.System?displayProperty=nameWithType>.
3333

3434
> [!NOTE]
35-
> The new behavior was reverted to the previous behavior in .NET 10 Preview 1.
35+
> The new behavior was reverted to the previous behavior in a .NET 9 servicing release and [.NET 10 Preview 1](../10.0/statusstrip-renderer.md).
3636
3737
## Affected APIs
3838

0 commit comments

Comments
 (0)