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)
        {
            ...
        }
        
        
    }

}
Blazor component check for valid bookings

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

Empty JSON object response

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

Valid response with JSON content type

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.

Confirmed the ViewModel was populated before passing to the response

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

How to serialize and deserialize JSON using C# - .NET
This article shows you how to use the System.Text.Json namespace to serialize to and deserialize from JSON in .NET. It includes sample code.
Newtonsoft.Json 12.0.3
Json.NET is a popular high-performance JSON framework for .NET
System.Text.Json and new built-in JSON support in .NET Core
In a world where JSON (JavaScript Object Notation) is everywhere it’s long been somewhat frustrating that .NET didn’t have built-in JSON support. JSON.NET is ... ...
What is the difference between a field and a property?
In C#, what makes a field different from a property, and when should a field be used instead of a property?