New to Telerik Reporting? Download free 30-day trial

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);
    }
}

See Also

In this article