Use Both 'System.Text.Json' and 'Newtonsoft.Json' for Serialization in ASP.NET Core
Environment
Product | Progress® Telerik® Reporting |
Description
A common requirement is to use System.Text.Json for serialization, instead of the required by the Reporting REST SErvice serialization package Newtonsoft.Json.
Suggested Workarounds
The most suitable workarounds are explained in the feature request Migrate to System.Text.Json for serialization, instead of using Newtonsoft.Json.
In this article, you may find a link to a sample with the implementation suggested in the Stackoverflow thread How to configure two JSON serializers and select the correct one based on the route.
The sample project may be downloaded from our reporting-samples
Github repository Two Json Serializers.
To ensure that the approach works, you may put break points in the conditional statements for the two formatters in the method ReadRequestBodyAsync
or WriteResponseBodyAsync
of the Controllers\CustomJsonFormatters.cs
file. The Newtonsoft.Json
formatter should be hit when the Reporting REST Service is called by the viewer or by calling manually the service, for example, at the ~/api/reports/version
. The System.Text.Json
formatter should be used when calling the Values controller, for example, at the end-point ~/api/values
.
Here is the code of the class that is not implemented in the Stackoverflow thread:
internal class MySuperJsonOutputFormatter : TextOutputFormatter
{
public MySuperJsonOutputFormatter()
{
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
SupportedMediaTypes.Add("application/json");
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
var httpContext = context.HttpContext;
var mvcOpt = httpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>().Value;
var formatters = mvcOpt.OutputFormatters;
TextOutputFormatter formatter = null;
Endpoint endpoint = httpContext.GetEndpoint();
if (endpoint.Metadata.GetMetadata<UseSystemTextJsonAttribute>() != null)
{
formatter = formatters.OfType<SystemTextJsonOutputFormatter>().FirstOrDefault();
}
else if (endpoint.Metadata.GetMetadata<UseNewtonsoftJsonAttribute>() != null)
{
// don't use `Of<NewtonsoftJsonInputFormatter>` here because there's a NewtonsoftJsonPatchInputFormatter
formatter = (NewtonsoftJsonOutputFormatter)(formatters
.Where(f => typeof(NewtonsoftJsonOutputFormatter) == f.GetType())
.FirstOrDefault());
}
else
{
throw new Exception("This formatter is only used for System.Text.Json InputFormatter or NewtonsoftJson InputFormatter");
}
await formatter.WriteResponseBodyAsync(context, selectedEncoding);
}
}