-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
PropertyNamingPolicy, PropertyNameCaseInsensitive, & Encoder options are honored when (de)serializing KeyValuePair instances with JsonSerializer
JsonSerializer will potentially serialize the "Key" and "Value" property names differently than in .NET Core 3.x/System.Text.Json 4.7.x (as influenced by the naming policy & encoder). When deserializing, the PropertyNamingPolicy and PropertyNameCaseInsensitive are honored. However, roundtripping is not broken as the literals "Key" and "Value" are special-cased to match when deserializing, to accommodate payloads that were serialized with previous versions.
Version introduced
.NET 5.0
Old behavior
On serialization:
The properties of KeyValuePair instances are always serialized as the literal "Key" and "Value", regardless of aforementioned options.
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
KeyValuePair<int, int> kvp = KeyValuePair.Create(1, 1);
Console.WriteLine(JsonSerializer.Serialize(kvp, options));
// Expected: {"key":1,"value":1}
// Actual: {"Key":1,"Value":1}On deserialization:
JsonException is thrown when the JSON property names are not precisely the "Key" and "Value" literals.
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
string json = @"{""key"":1,""value"":1}";
JsonSerializer.Deserialize<KeyValuePair<int, int>>(json, options); // JsonException thrownNew behavior
The aforementioned options are honored when serializing KeyValuePair instances.
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
KeyValuePair<int, int> kvp = KeyValuePair.Create(1, 1);
Console.WriteLine(JsonSerializer.Serialize(kvp, options));
// {"key":1,"value":1}On deserialization:
PropertyNamingPolicy and PropertyNameCaseInsensitive options are honored:
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
string json = @"{""key"":1,""value"":1}";
KeyValuePair<int, int> kvp = JsonSerializer.Deserialize<KeyValuePair<int, int>>(json);
Console.WriteLine(kvp.Key); // 1
Console.WriteLine(kvp.Value); // 1Note that the literals "Key" and "Value" are special-cased to match when deserializing, to accommodate payloads that were serialized with previous versions:
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
string json = @"{""Key"":1,""Value"":1}";
KeyValuePair<int, int> kvp = JsonSerializer.Deserialize<KeyValuePair<int, int>>(json);
Console.WriteLine(kvp.Key); // 1
Console.WriteLine(kvp.Value); // 1Reason for change
Substantial customer feedback indicated that the PropertyNamingPolicy should be honored. For completeness, the PropertyNameCaseInsensitive & Encoder options are also honored so that KeyValuePair<,> instances are treated the same as any other POCO.
Recommended action
For folks who find this change disruptive, the recommendation is to use a custom converter that implements the desired semantics.
Category
- ASP.NET Core
- C#
- Code analysis
- Core .NET libraries
- Cryptography
- Data
- Debugger
- Deployment
- Globalization
- Interop
- JIT
- LINQ
- Managed Extensibility Framework (MEF)
- MSBuild
- Networking
- Printing
- Security
- Serialization
- Visual Basic
- Windows Forms
- Windows Presentation Foundation (WPF)
- XML, XSLT
Affected APIs
Issue metadata
- Issue type: breaking-change