Moving from Json.NET (Newtonsoft) to System.Text.Json
In mid-2019, Microsoft released the System.Text.Json
library, intended to be a faster and lower memory JSON serializer / deserializer than the existing and still most popular Newtonsoft.Json
library. At the time, there were many features missing compared to Newtonsoft.Json
, and it was difficult to migrate. Now, 3 years on, it is easier.
Direct parsing
Where you previously used JToken.Parse
, use JsonNode.Parse
. See the documentation for more detail.
Basic serialization
Where you previously used JsonConvert.SerializeObject
, use JsonSerializer.Serialize
. The options passed in are different: Formatting.Indented
becomes a property on JsonSerializerOptions
: WriteIndented = true
. Other equivalents can be seen in the migration table: the most common are probably ContractResolver = new CamelCasePropertyNamesContractResolver()
-> PropertyNamingPolicy = JsonNamingPolicy.CamelCase
, ReferenceLoopHandling = ReferenceLoopHandling.Ignore
-> ReferenceHandler = ReferenceHandler.IgnoreCycles
(or PreserveReferencesHandling = PreserveReferencesHandling.All
-> ReferenceHandler = ReferenceHandler.Preservce
), and NullValueHandling = NullValueHandling.Ignore
-> DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
.
Note that System.Text.Json
by default does not serialize properties of derived classes. The easiest way to work around this is to pass the type to the Serialize
method: JsonSerializer.Serialize(item, item.GetType())
.
A more complicated way to work around this is to write a converter, overriding Write
to serialize to the specific types you want. Note that if you pass in the options object, you’ll get a stack overflow. If you want to use a non-default options, you’ll need to create a new options object (new JsonSerializerOptions(options)
) with a Converters
list that doesn’t contain the converter you’re currently writing.
After NET 7.0, the JsonDerivedType
attribute will be able to be used for this.
Basic deserialization
Where you previously used JsonConvert.DeserializeObject
, use JsonSerializer.Deserialize
. Adjust the options as described in the previous section. If you are accepting JSON which may come in an unknown case (e.g. Pascal / camel / other), set PropertyNameCaseInsensitive = true
in the options.
Note that System.Text.Json
does not support polymorphic deserialization until NET 7.0.
Attributes
Attributes are mostly identically named – e.g. JsonConstructor
, JsonConverter
. Some converters are slightly changed: e.g. StringEnumConverter
to JsonStringEnumConverter
. Autocomplete should find them.
Configuring ASP.NET
In ConfigureServices
in Startup.cs
, replace
services.AddControllers().AddNewtonsoftJson(opt => {
opt.UseCamelCasing(true)
opt.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
})
with
services.AddControllers().AddJsonOptions(o => {
var opts = o.JsonSerializerOptions;
opts.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
})
changing options as appropriate. ASP.NET uses web defaults by default:
PropertyNameCaseInsensitive = true
JsonNamingPolicy = CamelCase
NumberHandling = AllowReadingFromString
so these don’t have to be explicitly set.
If you have set up any other functionality to use Newtonsoft.Json
(e.g. AddSwaggerGenNewtonsoftSupport()
), remove this as well – the default has been System.Text.Json
since ASP.NET 3.0. After this, remove the packages Newtonsoft.Json
, Microsoft.AspNetCore.Mvc.NewtonsoftJson
and Swashbuckle.AspNetCore.Newtonsoft
from your csproj
files.