-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
Breaking change: New JsonSerializerDefaults.Web option leveraged by ASP.NET allows quoted numbers when deserializing JSON
In 5.0, we introduced a JsonSerializerDefaults enum along with a constructor on JsonSerializerOptions that takes this enum (dotnet/runtime#34626). This allows the creation of a JsonSerializerOptions instance with predetermined options, depending on the scenario. JsonSerializerDefaults.Web specifies the following options:
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
PropertyNameCaseInsensitive = true
NumberHandling = JsonNumberHandling.AllowReadingFromString
The number handling feature is new in .NET 5 (dotnet/runtime#30255) and allows custom number handling, including allowing the serializer to read quoted numbers (i.e JSON strings), rather than throw JsonException. With JsonSerializerDefaults.Web, the serializer is permitted to read strings as numbers.
In 3.x, the default JsonSerializerOptions used by ASP.NET Core specified the camel case naming policy, and allowed case-insensitive property naming matching, but per the serializer's capabilities in 3.x, reading JSON strings as numbers was not allowed. In 5.0, ASP.NET has adopted the new JsonSerializerDefaults.Web as the default (de)serialization options. This means that all ASP.NET applications by default will now allow reading JSON strings as numbers.
Note that the new JSON extension methods on HttpClient and HttpContent exposed by System.Net.Http.Json (dotnet/runtime#32937) also use the new JsonSerializerDefaults.Web options.
Version introduced
5.0
Old behavior
Quoted numbers in JSON payloads which were to map with number properties in object graphs on deserialization would cause JsonException to be thrown.
New behavior
Quoted numbers in JSON payloads which are to map with number properties in object graphs on deserialization are valid.
This is not the new behavior for the default stand-alone JsonSerializer or JsonSerializerOptions, but rather it is the default behavior specifically within ASP.NET Core apps, the System.Net.Http.Json package, or when the user opts-in and chooses the JsonSerializerDefaults.Web option.
This behavior is making a scenario more permissive, specifically going from throwing JsonException to successfully coercing a number from a JSON string. This is technically not a breaking change. However, since this will affect many ASP.NET Core apps, it is a significant behavioral change which should be advertised.
Reason for change
User feedback and requests for opt-in, more permissive number handling in JsonSerializer (dotnet/runtime#30255) indicated that many JSON producers (e.g. services across the web) emit quoted numbers. Allowing reading quoted numbers helps .NET applications successfully parse these payloads by default in web contexts. This API is exposed via JsonSerializerDefaults.Web so that there is a handy way to specify the same options across different application layers e.g. client, server, shared. More detail here - dotnet/runtime#42240 (comment).
Recommended action
If this change is disruptive, e.g. the strict/default number handling in JsonSerializer is depended upon for validation, the previous behavior can be reenabled by setting the JsonSerializeOptions.NumberHandling option used by the application to JsonNumberHandling.Strict.
For ASP.NET Core MVC and web API applications, this can be configured in Startup using the following snippet:
services.AddControllers()
.AddJsonOptions(options.NumberHandling = JsonNumberHandling.Strict);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
JsonSerializer.Deserialize
JsonSerializer.DeserializeAsync
Issue metadata
- Issue type: breaking-change