The new System.Text.Json APIs are aimed at making JSON a first class citizen in .NET Core and bring some significant performance enhancements and memory consumption improvements for JSON serialisation. They will replace the requirement of referencing the third party Newtonsoft Json packages entirely as they continue to mature.
Unsuprisingly, James Newton-King has been involved with the .Net core team on the new implementation
A Road Well Travelled
- Newtonsoft.Json (also known as Json.NET) – The current industry-standard serializer. Was integrated into ASP.NET even though it was 3rd party. One of the #1 NuGet packages of all time.
- System.Text.Json – The brand new serializer from Microsoft. Designed to be Supposedly faster and more lightweight than Newtonsoft.Json. Integrated by default with the new ASP.NET Core 3.x projects. It’s part of the .NET framework itself, so there are no NuGet dependencies and less conflict management.
Try It Out
As the new serializer is baked into the framework there is nothing required in order to benefit from the automatic serialisation of models being returned as JSON for ASP.NET Core Controller Action Methods.
There are however a few considerations and workarounds to be aware of as well as a fallback pattern if required.
Model returned as null {}
As part of a new Blazor WebAssembly application i am developing i wanted to consume a WebAPI endpoint for live booking information. As i already have such an endpoint i put together a few lines of code in my Blazor component to call the API. (over simplified for brevity)
@code {
private BookingAvailabiltyViewModel bookings;
protected override async Task OnInitializedAsync()
{
try
{
bookings = await
Http.GetFromJsonAsync<BookingAvailabiltyViewModel>
("Availability?van=california");
}
catch (Exception exception)
{
...
}
}
}

I was expecting a collection of bookings but instead i received and empty JSON response.

Looking at the response it returned a 200 and i also know other clients are consuming the booking service via a different API.

I stepped through the code and confirmed the service was populating my POCO as expected before being handed the result inside the Action method on the Controller.

So this led me to identify whether the populated object was actually being serialized, as expected, by the JSON serializer as part of the response generation.
The Problem
After taking a quick look at the new System.Text.Json docs i simply serialized my ViewModel as a string and there it was indeed empty {}.
//uncomment to force the the serialization to string
var serialized = JsonSerializer.Serialize(vm);
The Solution
After some fairly quick investigation and the read of the references included below, the lights came on and it was the fact i was using fields instead of properties on my model class. The current implementation of the .Net Core serializer ignores fields at the time of writing this article.
Although the underlying POCO objects were exposing their members as properties, the ViewModel which sat on top exposed it's members as fields.
public class BookingAvailability
{
public DateTime From { get; set; }
public DateTime To { get; set; }
public string Status { get; set; }
public string Tooltip { get; set; }
}
public class BookingAvailabiltyViewModel
{
public bool Enabled = false;
public List<BookingAvailability> Bookings;
}
When i stopped to think about it for a moment, it makes sense. Fields are generally private and exposed as properties, hiding the internals and enabling more complex logic to be performed on the get or set of the underlying value.
The Fallback
Now it maybe that you run into a more complex scenario having relied on the Newtonsoft.Json packages for most of your .NET career up to now and cannot afford the necessary refactor workarounds to use the built in .Net Core version at this time. Fortunately the .NET Core team have allowed for this with a fallback option for the time being.
Simply install the Newtonsoft.Json NuGet package, being sure to target .Net core 3.x or in the case of Blazor .Net Standard 2 and configure the service as usual.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson();
}
In Conclusion
Having read and listened to a number of posts from the .NET Core team the JSON enhancements are set to add some great performance and productivity benefits for us as Blazor developers and the .Net community as a whole. But as with all advancement some things are likely to be impacted. The team are still evaluating the decisions and use cases to shape the implementation for features such as whether to support fields or stick with properties only and our valued feedback will help drive such outcomes.
Although this particular issue slowed me down for a couple of hours it has highlighted to me that it is always good to re-evaluate the basics and stick to best practices where possible. Moving to Blazor WebAssembly in earnest, especially now since it's official release a couple of days ago, brings so much potential as it is now part of the core .NET Eco system. Solutions and workarounds we find in one .Net Core library can be applied across all our code bases.
References


