preface

Maybe some of you already know that. Microsoft added built-in support for JSON in NET Core 3.0. .NET developers have long been used to working with JSON using the powerful Json.NET library. So why did.NET add JSON built-in support? Recently, the official.net blog published another post explaining why this is done and how the API is used. The original address: https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/. Json and Json.NET.

System. Text. Json is introduced

The system.text. Json namespace provides functionality for serializing and deserializing JavaScript object representations (Json). The System.text. Json library is included with.net Core 3.1 and later runtimes. For other target frameworks, install the System.text. Json NuGet package. Packages support the following frameworks:

  • .NET Standard 2.0 and later
  • .NET Framework 4.7.2 and later
  • .NET Core 2.0, 2.1, and 2.2

System.text. Json focuses on performance, security, and standards compliance. It has some important differences in default behavior and is not intended to have the same functionality as newtonsoft.json. For some scenarios, system.text. Json has no built-in functionality, but there are suggested workarounds.

Difference between newtonsoft. Json and system.text. Json

  • Supported by supported features. fromSystem.Text.JsonObtaining similar behavior may require the use of properties or global options.
  • Unsupported. There may be a solution. The solution isCustom converter, they may not be available withNewtonsoft.JsonThe exact same function. For some of these features, sample code is provided as examples. If you depend on thatNewtonsoft.JsonFeatures that require modifications to the.NET object model or other code changes.
  • Unsupported, solution not feasible or available. If you depend on thatNewtonsoft.JsonFunction, you cannot migrate without making significant changes.
Newtonsoft. Json functions System. Text. Json equivalent
Deserialization is case insensitive by default ✔ ️PropertyNameCaseInsensitive global Settings
Camel case attribute name ✔ ️PropertyNamingPolicy Global setting
Minimum character escape ✔ ️Strict character escape, configurable
NullValueHandling.IgnoreGlobal Settings ✔ ️DefaultIgnoreCondition Global option Properties are conditionally ignored
Allow comments ✔ ️ReadCommentHandling Global Settings
Allow trailing commas ✔ ️AllowTrailingCommas global Settings
Custom converter registration ✔ ️The priority order is different
By default, there is no maximum depth ✔ ️The default maximum depth is 64, which is configurable
PreserveReferencesHandlingGlobal Settings ✔ ️ReferenceHandling global setting
Serialize or deserialize quoted numbers ✔ ️NumberHandling Global setting, the [JsonNumberHandling] feature
Deserialize to immutable classes and structures ✔ ️JsonConstructor, C# 9 record
Support field ✔ ️IncludeFields Global Settings, [JsonInclude] feature
DefaultValueHandlingGlobal Settings ✔ ️DefaultIgnoreCondition Global Settings
[JsonProperty]On theNullValueHandlingSet up the ✔ ️JsonIgnore features
[JsonProperty]On theDefaultValueHandlingSet up the ✔ ️JsonIgnore features
Deserialize with non-string keysDictionary ✔ ️The supported
Support for non-public property libraries and getters ✔ ️JsonInclude features
[JsonConstructor]features ✔ ️[JsonConstructor] features
Supports a wide range of types ⚠ ️Some types require custom converters
Polymorphic serialization ⚠ ️Unsupported, workaround, example
Polymorphic deserialization ⚠ ️Unsupported, workaround, example
Deserialize the inferred type toobjectattribute ⚠ ️Unsupported, workaround, example
The JSONnullDeserialize text to a value type that cannot be NULL ⚠ ️Unsupported, workaround, example
[JsonProperty]On the characteristics ofRequiredSet up the ⚠ ️Unsupported, workaround, example
DefaultContractResolverUsed to ignore attributes ⚠ ️Unsupported, workaround, example
DateTimeZoneHandling,DateFormatStringSet up the ⚠ ️Unsupported, workaround, example
The callback ⚠ ️Unsupported, workaround, example
JsonConvert.PopulateObjectmethods ⚠ ️Unsupported, solution
ObjectCreationHandlingGlobal Settings ⚠ ️Unsupported, solution
Add to collection without setter ⚠ ️Unsupported, solution
ReferenceLoopHandlingGlobal Settings ❌ Is not supported
supportSystem.Runtime.Serializationfeatures ❌ Is not supported
MissingMemberHandlingGlobal Settings ❌ Is not supported
Attribute names without quotes are allowed ❌ Is not supported
Single quotes are allowed around string values ❌ Is not supported
Allow non-string JSON values for string attributes ❌ Is not supported

Default JsonSerializer behavior versus Newtonsoft.json

System.text. Json is strict by default, avoiding any guesswork or interpretation on behalf of the caller and emphasizing deterministic behavior. The library is specifically designed for performance and security. Newtonsoft.json is flexible by default. This fundamental difference in design is behind many of the following specific differences in default behavior.

Case insensitive deserialization

During deserialization, newtonsoft.json does case-insensitive attribute name matching by default. The system.text. Json default is case sensitive, which provides better performance because it performs exact matching. For information on how to perform case-insensitive matching, see Case-insensitive Attribute Matching.

If you use system.text. Json indirectly with ASP.NET Core, you don’t need to do anything to get behavior similar to newtonsoft.json. ASP.NET Core specifies Settings for camel case attribute names and case-insensitive matching when using system.text. Json.

By default, ASP.NET Core also allows you to deserialize quoted numbers.

Minimum character escape

During serialization, newtonsoft.json is relatively lax about letting characters pass without escaping. That is, it does not replace them with \uxxxx (where XXXX is the code point for a character). When a character is escaped, it does so by emitting ‘before the character (for example,’ will become ‘). System.text. Json escapes more characters by default to provide deep defense protection against cross-site scripting (XSS) or information leakage attacks, and performs this using six-character sequences. System. Text. Json will by default escape all non-ascii characters, so if in Newtonsoft StringEscapeHandling used in Json. EscapeNonAscii, you do not need to do anything. System.text. Json also escapes HTML-sensitive characters by default. For information on how to replace the default System.text. Json behavior, see Custom Character encodings.

annotation

During deserialization, newtonsoft.json ignores comments in Json by default. The system.text. Json default is to throw exceptions for annotations, because they are not covered by the RFC 8259 specification. For information on how to allow comments, see Allow Comments and Trailing commas.

Trailing comma

During deserialization, newtonsoft.json ignores the trailing comma by default. It will ignore the multiple trailing comma (for example [{” Color “:” Red “}, {” Color “:” Green “},,]). The system.text. Json default is to throw an exception for trailing commas because they are not allowed by the RFC 8259 specification. For information on how to make system.text. Json accept them, see Allowing comments and Trailing commas. Multiple trailing commas cannot be allowed.

Converter registration priority

The newtonsoft.json registration priority for the custom converter is shown below:

  • Properties on properties
  • Properties on types
  • Converters set

This order means that custom Converters in the Converters collection are replaced by Converters registered by applying features at the type level. Both registrations are replaced by property-level features.

Json registration priorities for custom converters are different:

  • Properties on properties
  • Collection of Converters
  • Properties on types

The difference here is that custom Converters in the Converters collection replace type-level features. The purpose of this priority order is to enable the runtime to change alternative design-time options. The priority cannot be changed.

For more information about registering a custom converter, see Registering a Custom Converter.

Maximum depth

Newtonsof. Json has no maximum depth limit by default. For the System. Text. Json, the default limit is 64, but by setting the JsonSerializerOptions. MaxDepth configured.

If you use ASP.NET Core with system.text. Json, the default maximum depth limit is 32. The default value is the same as the default value for the model binding and is set in the JsonOptions class.

JSON string (property name and string value)

During deserialization, newtonsoft.json accepts property names enclosed in double, single, or no quotes. It accepts string values enclosed in double or single quotation marks. For example, newtonsoft.json accepts the following Json:

{
  "name1": "value",
  'name2': "value",
  name3: 'value'
}
Copy the code

System.text. Json accepts only property names and string values in double quotes, as this format is required by the RFC 8259 specification and is the only format that is considered valid Json.

Values enclosed in single quotes cause a JsonException with the following message:

' '' is an invalid start of a value.
Copy the code

A non-string value for a string attribute

Newtonsoft.Json accepts non-string values (such as numbers or text true and false) to deserialize properties into type strings. Json successfully deserialized to the following class: newtonsoft.json

{
  "String1": 1."String2": true."String3": false
}
Copy the code
public class ExampleClass
{
    public string String1 { get; set; }
    public string String2 { get; set; }
    public string String3 { get; set; }}Copy the code

System.text. Json does not deserialize non-string values into string attributes. A non-string value received by a string field causes a JsonException with the following message:

The JSON value could not be converted to System.String.
Copy the code

Solution using JsonSerializer

Some of the following solutions are not supported by built-in features, but there are workarounds. The solution is custom converters, which may not provide exactly the same functionality as newtonsoft.json. For some of these features, sample code is provided as examples. If you rely on these newtonsoft.json features, migration requires modifications to the.NET object model or other code changes.

For some of the following solutions, solutions are not available or not available. If you rely on these newtonsoft.json features, you can’t migrate without major changes. For details, see ## JsonSerializer

performance

Since this feature is strongly performance-driven, we wanted to share some of the advanced performance features of the new API.

Keep in mind that these are based on preview releases and the final numbers are likely to vary. We are also tweaking the default behavior (for example, case sensitivity) that affects performance. Note that these are microbenchmarks. Your mileage is bound to vary, so if performance is critical to you, make sure you do your own measurements for the scenario that best represents your workload.

The original System. Text. Json

A microbenchmark is all you need to do to compare System.text. Json with Json.NET and get the following results:

scenario speed memory
deserialization 2 times faster Flat or lower
serialization 1.5 times faster Flat or lower
File (read only) 3 to 5 times faster <1 MB No allocation
The reader 2-3 times faster No allocation (until materialize values)
The writer 1.3 to 1.6 times faster No distribution

ASP.NET Core MVC system.text. Json

We wrote an ASP.NET Core application that dynamically generates data and then serializes and deserializes it from the MVC controller. Then we change the payload size and measure the result:

JSON deserialization (input)

describe Throughput (RPS) CPU (%) Memory (MB)
Newtonsoft. Json – 500 B 136435 95 172
System. Text. Json – 500 B 167861 94 169
Newtonsoft. Json – 2.4 KB 97137 97 174
System. Text. Json – 2.4 KB 32026 96 169
Newtonsoft. Json – 40 KB 7712 88 212
System. Text. Json – 40 KB 16625 96 193

JSON serialization (output)

describe Throughput (RPS) CPU(%) Memory (MB)
Newtonsoft.Json – 500 B 120273 94 174
System.Text.Json – 500 B 145631 94 173
Newtonsoft.Json – 8 KB 35408 98 187
System.Text.Json – 8 KB 56424 97 184
Newtonsoft.Json – 40 KB 8416 99 202
System.Text.Json – 40 KB 14848 98 197

For the most common payload size, System.text. Json increases MVC throughput by about 20% during input and output formatting, with less memory footprint.