Try the new System.Text.Json APIs
For .NET Core 3.0, we’re shipping a brand new namespace called System.Text.Json with support for a reader/writer, a document object model (DOM), and a serializer. In this blog post, I’m telling you why we built it, how it works, and how you can try it.
We also have a video:
Getting the new JSON library
- If you’re targeting .NET Core. Install the latest version of the .NET Core 3.0 preview. This gives you the new JSON library and the ASP.NET Core integration.
- If you’re targeting .NET Standard or .NET Framework. Install the System.Text.Json NuGet package (make sure to include previews and install version 4.6.0-preview6.19303.8 or higher). In order to get the integration with ASP.NET Core, you must target .NET Core 3.0.
The future of JSON in .NET Core 3.0
JSON has become an essential part of virtually all modern .NET applications and in many cases even surpassed the usage of XML. However, .NET hasn’t had a (great) built-in way to deal with JSON. Instead, we’ve relied on Json.NET until now, which continues to serve the .NET ecosystem well.
We’ve decided that we needed to build a new JSON library:
- Provide high-performance JSON APIs. We needed a new set of JSON APIs that are highly tuned for performance by using
Span<T>and can process UTF-8 directly without having to transcode to UTF-16
stringinstances. Both aspects are critical for ASP.NET Core, where throughput is a key requirement. We considered contributing changes to Json.NET, but this was deemed close to impossible without either breaking existing Json.NET customers or compromising on the performance we could achieve. With
System.Text.Json, we were able to gain 1.3x – 5x speed up, depending on the scenario (see below for more details). And we believe we can still squeeze out more.
- Remove Json.NET dependency from ASP.NET Core. Today, ASP.NET Core has a dependency on Json.NET. While this provides a tight integration between ASP.NET Core and Json.NET, it also means the version of Json.NET is dictated by the underlying platform. However, Json.NET is frequently updated and application developers often want to — or even have to — use a specific version. Thus, we want to remove the Json.NET dependency from ASP.NET Core 3.0, so that customers can choose which version to use, without fearing they might accidentally break the underlying platform.
- Provide an ASP.NET Core integration package for Json.NET. Json.NET has basically become the Swiss Army knife of JSON processing in .NET. It provides many options and facilities that allow customers to handle their JSON needs with ease. We don’t want to compromise on the Json.NET support customers are getting today. For example, the ability to configure the JSON serialization in ASP.NET Core via the
AddJsonOptionsextension method. Thus, we want to provide the Json.NET integration for ASP.NET Core as a NuGet package that developers can optionally install, so they get all the bells and whistles they get from Json.NET today. The other part of this work item is to ensure we have the right extension points so that other parties can provide similar integration packages for their JSON library of choice.
For more details on the motivation and how it relates to Json.NET, take a look at the announcement we made back in October.
Using System.Text.Json directly
For all the samples, make sure you import the following two namespaces:
Using the serializer
System.Text.Json serializer can read and write JSON asynchronously and is optimized for UTF-8 text, making it ideal for REST API and back-end applications.
By default, we produce minified JSON. If you want to produce something that is human readable, you can pass in an instance of
JsonSerializerOptions to the serializer. This is also the way you configure other settings, such as handling of comments, trailing commas, and naming policies.
Deserialization works similarly:
We also support asynchronous serialization and deserialization:
You can also use custom attributes to control serialization behavior, for example, ignoring properties and specifying the name of the property in the JSON:
We currently don’t have support for F# specific behaviors (such as discriminated unions and record types), but we plan on adding this in the future.
Using the DOM
Sometimes you don’t want to deserialize a JSON payload, but you still want structured access to its contents. For example, let’s say we have a collection of temperatures and want to average out the temperatures on Mondays:
The JsonDocument class allows you to access the individual properties and values quite easily.
Using the writer
The writer is straight forward to use:
The reader requires you to switch on the token type:
Integration with ASP.NET Core
Most use of JSON inside of ASP.NET Core is provided via the automatic serialization when accepting or returning object payloads, which in turn means that most of your application’s code is agnostic to which JSON library ASP.NET Core is using. That makes it easy to switch from one to another.
You can see the details on how you can enable the new JSON library in MVC and SignalR later on in this post.
Integration with ASP.NET Core MVC
In Preview 5, ASP.NET Core MVC added support for reading and writing JSON using
System.Text.Json. Starting with Preview 6, the new JSON library is used by default for serializing and deserializing JSON payloads.
Options for the serializer can be configured using MvcOptions:
If you’d like to switch back to the previous default of using
Newtonsoft.Json, do the following:
- Install the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.
ConfigureServices()add a call to
- Support for OpenAPI / Swagger when using
System.Text.Jsonis ongoing and unlikely to be available as part of the 3.0 release.
Integration with SignalR
System.Text.Json is now the default Hub Protocol used by SignalR clients and servers starting in ASP.NET Core 3.0 Preview 5.
If you’d like to switch back to the previous default of using
Newtonsoft.Json, then you can do so on both the client and server.
- Install the
- On the client add
- On the server add
Since this feature is heavily motivated by performance, we’d like to share some high-level performance characteristics of the new APIs.
Please keep in mind that these are based on preview builds and the final numbers will most likely differ. We’re also still tweaking default behaviors which will affect performance (for example, case sensitivity). Please note that these are micro benchmarks. Your mileage will most certainly differ, so if performance is critical for you, make sure to make your own measurements for scenarios that best represent your workload. If you encounter scenarios you’d like us to optimize further, please file a bug.
Just doing micro benchmarks to compare
System.Text.Json with Json.NET yields the following output:
|Deserialization||2x faster||Parity or lower|
|Serialization||1.5x faster||Parity or lower|
|Document (read-only)||3-5x faster||~Allocation free for sizes < 1 MB|
|Reader||2-3x faster||~Allocation free (until you materialize values)|
|Writer||1.3-1.6x faster||~Allocation free|
System.Text.Json in ASP.NET Core MVC
We’ve written an ASP.NET Core app that generates data on the fly that is then serialized and deserialized from MVC controllers. We then varied the payload sizes and measured the results:
JSON deserialization (input)
|Description||RPS||CPU (%)||Memory (MB)|
JSON serialization (output)
|Description||RPS||CPU (%)||Memory (MB)|
For the most common payload sizes,
System.Text.Json offers about 20% throughput increase in MVC during input and output formatting with a smaller memory footprint.
In .NET Core 3.0, we’ll ship the new
System.Text.Json APIs, which provide built-in support for JSON, including reader/writer, read-only DOM, and serializer/deserializer. The primary goal was performance and we see typical speedups of up to 2x over Json.NET, but it depends on your scenario and your payload, so make sure you measure what’s important to you.
ASP.NET Core 3.0 includes support for
System.Text.Json, which is enabled by default.
System.Text.Json a try and send us feedback!
Yes! Just what I needed for an upcoming edge device. Thank you.
Ok, so just like always, you built your own, which will be substandard, incompatible, and slower for real world cases. I bet your contrived examples were faster… publish all the real world cases that came in slower… in the interest of full disclosure.
And to top it off, you wrote it into System.Text.Json namespace, so now we’ll usually have two JSON libraries deployed: JSON.net and yours.
Brilliance! Classic Microsoft “Not Invented Here” syndrome that plagues the entire MS infrastructure. Note how the worst security bugs are mostly Microsoft’s? There’s an underlying symptom for that… and its because you keep copying other people’s stuff and trying to write it better, while not understanding the reasons for why that stuff exists in the first place.
James Newton-King (the author of Json.NET) joined Microsoft and I’m pretty sure has been working with them to develop their JSON libraries.
So it’s not really Microsoft going it alone – it’s Microsoft bringing “JSON.net” into their architecture as a standalone piece of code.
Get therapy nutjob. You sound like a deranged lunatic who’s still ranting because Windows 3.1 crashed. Question, if the performance numbers weren’t contrived, will you throw yourself off a building, and forever spare us the pathetic, tired, anti-Microsoft talking points?
I’ve crossed paths with Mr. Newton a few times online in the past and he’s always been pretty lucid, to the point, and correct in his observations and descriptions.
You on the other hand were quick to judge without doing the rational thing of asking him for examples or data to back his claims and complaints. You read his frustration/anger/saltiness and completely misinterpreted it as some form of mental illness and tried to use it as a straw man to attack.
Perhaps you should consider saying nothing if you or arent interested in hearing what someone is saying.
“I bet your contrived examples were faster”
Did he provide a SCINTILLA OF EVIDENCE to support that libel? No. Conclusion -> Filth
“And to top it off, you wrote it into System.Text.Json namespace, so now we’ll usually have two JSON libraries deployed: JSON.net and yours.”
What does the namespace have to do with how many libraries you deploy. NOTHING. Conclusion -> Laughably inexperienced.
“Classic Microsoft “Not Invented Here” syndrome that plagues the entire MS infrastructure.”
Outdated talking point at best. Conclusion -> Deranged bitter loser
“Note how the worst security bugs are mostly Microsoft’s?”
Laughably incorrect. Conclusion -> Lying filth
His ENTIRE POST was lies and diatribes with no factual basis in reality. You know what call someone who operates in their own little universe. INSANE. And the normal course of action to treat that is therapy.
@Jack Bond I started the sentence with “I bet” which means I dont have evidence beyond my experience with Microsoft v1 products in general. I specifically used “I bet” because I’m using my intuition. Anybody can write a JSON serializer that would be 100 times faster than even System.Net.json where it only goes one level deep, doesnt respect type converters, etc. That would be contrived. Won’t work in the real world.
It’s no secret that Microsoft frequently copies ideas from other software companies, the v1 is “revolutionary” but slow, v2 “fixes the problems” and v3 is the one actually useful in real production scenarios.
My original point, which you seem to have lost in your dissertation, was that there’s already a perfectly good JSON serialization library that is tried and true, has extensve open source support, and is basically DE-FACTO standard of JSON serialization for the dotnet framework.
Introducing another set of types is ludicrous and will create the scenario where “old libraries” still use JSON.net and “new libraries” use this shadow of the original, and the types will not match.
Here’s what they SHOULD have done. Create a standardized set of INTERFACES for a JSON serializer for dotnet, and upgrade JSON.net to support those interfaces, so that JSON.net is still DE-FACTO library and is backward compatible with “old libraries”.
This piggybacks on the concept that the dotnet framework defauilt assembly binding needs to be relaxed (and Nuget actually does this with all those annoying binding redirects) to semver standards or at least binding on the “major” portion of the version and not all four octets of the assembly version. I do wholeheartedly understand that this drastically changes how dotnet FRAMEWORK does binding, but dotnet CORE should’ve adopted this standard but they chose to stick to the incredibly annoying assembly binding redirects path.
tl;dr system.net.json should just be a few interfaces for allowing asp.net core, web api, library X, library Y to all use an interchangable set of interfaces for serializing/deserializing and working with JSON data. JSON.net should be the first library to implement it. This is how you make thing work interchangably. Not create your own, call it better, and then creating the “I use JSON.net” vs “I use System.text.json” flame wars.
@Andrew Stanton Thank you for defending me.
It’s funny because people try to read speech inflections in text that can be quite different from how I intend them to be.
I simply stated that a typical thing is to promote a contrived example that shows 1.5x speed increase over the existing library, without acknowledging that the new library may be fast, however it will not handle all the scenarios that have legitimately been baked into the existing library.
Didnt ASP.Net Core claim huge speed increases for v1 and then the very next versions slowed down because it had to handle the messiness of real world HTTP protocol dealings? That is also my point with System.Net.Json… in the end I bet the “speed increase” will be exactly the same as the existing JSON.net
@Jack Bond “get therapy nutjob” is quite beneath the quality of conversation while personally attacking me and adds zero to the conversation, and only makes YOU look like a deranged lunatic yourself,
I’m pointing out something that everybody knows to be true… Microsoft subverts most software, slap it together, and the v1 sucks, the v2 still sucks but less, and the v3 is decent. Azure Pipelines is the most recent case in point.
Eric Newton, you’re not adding anything usefull to this discussion besides your emotional diahreea. All of this had been widely discussed before; take your time and read the announcement at https://github.com/dotnet/corefx/issues/33115 — there’s also several quotes and posts of the author of Json.Net (JamesNK) explaining the reasoning.
According to his own words:
“Json.NET was created over 10 years ago, and since then it has added a wide range of features aimed to help developers work with JSON in .NET. In that time Json.NET has also become far and away NuGet’s most depended on and downloaded package, and is the go-to library for JSON support in .NET. Unfortunately, Json.NET’s wealth of features and popularity works against making major changes to it. Supporting new technologies like
Span<T>would require fundamental breaking changes to the library and would disrupt existing applications and libraries that depend on it.
Going forward Json.NET will continue to be worked on and invested in, both addressing known issues today and supporting new platforms in the future. Json.NET has always existed alongside other JSON libraries for .NET, and there will be nothing to prevent you using one or more together, depending on whether you need the performance of the new JSON APIs or the large feature set of Json.NET.”
“Json.NET isn’t going away. You aren’t losing anything. This is another option for simple and high performance scenarios.”
I’m going to ignore your first few sentences since they take personal shots at me, instead of addressing the core of the issue I was addressing.
Thanks for informing us of that issue on corefx since the blog poster here made zero mention of it. Had he done so, perhaps some of us could have a more informed opinion about it.
You could also just inform yourself instead of making excuses that others didn’t inform you for you. The info isn’t hidden.
I used this serializer im my web applications. For me it has easier to use API, and i managed to writer a custom converter for byte arrays. Unfortunately the Json.NET and as well as the new System.Text.Json serialize byte arrays to Base64 strings which is a nuisance (and i think it’s an incorrect behavior). But a custom converter helped with this problem. It was easier to write it for System.Text.Json . And another good thing, that it (System.Text.Json) supports an async serialization.
public class BytesConverter : JsonConverter<byte>
public override byte Read(
ref Utf8JsonReader reader,
JsonSerializerOptions options) => reader.GetString()?.ConvertToBinary();
public override void Write(
byte value, JsonSerializerOptions options)
foreach (var val in value)
/// serialize an object to JSON
public class Serializer : ISerializer
private static readonly JsonSerializerOptions Options = new JsonSerializerOptions();
public string Serialize(object obj)
return JsonSerializer.Serialize(obj, Options);
public Task SerializeAsync<T>(T obj, Stream stream)
return JsonSerializer.SerializeAsync<T>(stream, obj, Options);
public object DeSerialize(string input, Type targetType)
return JsonSerializer.Deserialize(input, targetType, Options);
Is the plan to create JSON schema APIs, as well? Good stuff and great work team!
One would hope so given that Newtonsoft charges money for it. Given how ubiquitious JSON is, .NET should have JSON schema support by default, just like it supported XML schema before. However, many people disagree with me as I raised this issue on GitHub and everyone said that no one needs it and that it’s better to rely on random other NuGet libraries to do it that have no documentation.
The Json.NET versioning situation is a serious pain-point atm, so it’s good to see an attempt to solve it. Can’t help but think about standards though (and yes, I did note that Json.NET isn’t being discarded, but it’s needed for “some use case” then I foresee having to try to keep the settings for two different libraries consistent within one codebase – ugh). Also, what’s the story on camelCase? As this is brand-new library that doesn’t have to maintain backward compatibility, any chance of taking the plunge and defaulting to idiomatic casing on both sides?
Regarding versioning, this isn’t really JSON.net’s fault, its the extremely strict assembly binding that is akin to old school COM interfaces from 20 years ago when dotnet framework started out. I’ve been railing on this for a long time, and it got really exascerbated when Nuget came and would get libraries+dependencies. We ended up back in the COM dll-hell days of incompatible binary interfaces carried forward into dotnet framework. I found that ironic since the runtime has things like “MissingMethodException” thats thrown when the method signature cant be found on a type when a loose binding is used.
For instance, a lot of applications use log4net with some using one particular build versus another for a time. The only way to get two libraries to coexist with log4net v1 is via an assembly binding redirect that ends up effectively applying semver to the binding.
Unfortunately NetCore seems to do the same thing, and IMO is the wrong move. It should use a semver style assembly binding technique with specific assembly bindings used to sidestep problematic versions encountered somehow.
Honestly, it seems like a solution in search of a problem. We’ve been using the newtonsoft product for years and it’s one of the few modules that has never caused us problems.
But, whatever. I just hope it doesn’t cause conflicts.
Must be great not having to worry about leaving performance on the table for your APIs.
If you look a bit around though you’ll find that other people use protobuff or the JSON library by the stackoverflow people because while newtonsoft.json is very powerful and customisable its performance characteristics are not particularly great.
Getting a high performance low level library for IO will benefit everyone in the long run.
Thats a good point too. However, I value correctness over speed. System.net.json v1 might be speedier, but JSON.net is tried and true.
Excellent point. A solution in search of a problem that didn’t exist until now.
Now there will be two competing type libraries de-facto JSON serialization libraries. This is a step in the wrong direction.
You’re simply mistaken if you think this is not a problem currently. It might not be for your performance-insenstive use cases, which is fair – for most applications this is not that big of a deal.
But if you’re actually having to work on applications that require good scalability, Newtonsoft.Json is decidedly not the framework you’d be using anyhow. Here just one of those solutions to a non existing problem that’s in use on StackOverflow and other sites: https://github.com/kevin-montrose/Jil
It’s good to have faster JSON serialization and deserialization in .Net Core. However if people really care about performance or serialization efficiency JSON is just the wrong format. It’s for when you need direct human readability and editing. E.g. in source control. CBOR is the best current choice when you don’t need direct human readability. JSON is way overused.
Very nice. Thank you for the article. Read DOM access is nice but what about write access? Are there any plans for ability to modify DOM?
What is the performance improvement on techempower JSON serialization benchmarks ?
I just tried converting a side project to use this but unfortunately it doesn’t support parameters in constructors and therefore doesn’t support immutable objects, which is a shame. I’d come to accept that with the old XML serializers but I’ve been using it happily in Json.NET for a while.
I’ve added a comment to https://github.com/dotnet/corefx/issues/38163
We got your immutable objects covered here in case you want to return back to the fold, @Mark: https://github.com/wojtpl2/ExtendedXmlSerializer
XML still natively supports comments as well… without any hacky booleans that technically break standards. 😉 Don’t forget about XSLT, etc.
Amazing, thanks, looks neat! I’ll bear it in mind next time I work on some XML serialization. I too quite like XML and have used it happily lots before.
So why is the new API using Parse and ToString instead of Serialize and Deserialize? Every prior serializer i’ve seen in the BCL and in the wild also used these terms and you can’t get around describing those features using Serialize(ation) and Deserialize.
Another excellent point, where the Microsofties build something in a cigar-smoke back room, declare it to be the fix for all the JSON serialization problems, and foist it out there with zero input.
Maybe I missed it, but I don’t think anybody had any idea that in the banals of Microsoft, they realized JSON.net was too useful and needed to be replaced with another JSON serialization library.
Already renamed: https://github.com/dotnet/corefx/pull/38933
Is there any known issues with round tripping using JsonSerializer.WriteAsync and JsonSerializer.ReadAsync between 2 threads/TCP clients in the same process? I’m trying to test it out with a very simple test app, and have verified that the JSON is getting written to the socket, but the ReadAsync never returns.