Handling json pretty print param in ASP.NET Core API application Handling json pretty print param in ASP.NET Core API application json json

Handling json pretty print param in ASP.NET Core API application


If you want it to be global, you can register a custom output formatter. Here's a working example I made. You're free to use.

It works by reading a header named "jsonformat" for a named json serializer setting, such as one named "pretty". If no header is present, or the header is invalid, it falls back to the default json serializer settings. This might be a cleaner approach if you want it available globally - no action filters required.

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc.Formatters;using Microsoft.Extensions.Primitives;using Newtonsoft.Json;...public class NamedFormatJsonOutputFormatter : JsonOutputFormatter{    private readonly IDictionary<string, JsonSerializerSettings> _customJsonSettings;    private readonly IDictionary<string, JsonSerializer> _customSerializers;    public NamedFormatJsonOutputFormatter(JsonSerializerSettings defaultSerializerSettings, IDictionary<string, JsonSerializerSettings> customJsonSettings, ArrayPool<char> charPool) : base (defaultSerializerSettings, charPool)    {        _customJsonSettings = customJsonSettings;        _customSerializers = new Dictionary<string, JsonSerializer>();    }    protected virtual JsonSerializer CreateCustomJsonSerializer(string serializerName)    {        JsonSerializer outputSerializer;        var exists = _customSerializers.TryGetValue(serializerName, out outputSerializer);        if (!exists)        {            var settings = _customJsonSettings[serializerName];            outputSerializer = JsonSerializer.Create(settings);            _customSerializers[serializerName] = outputSerializer;        }        return _customSerializers[serializerName];    }    public void WriteObjectWithNamedSerializer(TextWriter writer, string serializerName, object value)    {        if (writer == null)        {            throw new ArgumentNullException(nameof(writer));        }        using (var jsonWriter = CreateJsonWriter(writer))        {            var jsonSerializer = CreateCustomJsonSerializer(serializerName);            jsonSerializer.Serialize(jsonWriter, value);        }    }    public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)    {        var jsonSerializerNameHeader = context.HttpContext.Request.Headers.FirstOrDefault(h => h.Key == "jsonformat" && h.Value.Intersect(_customJsonSettings.Keys).Any());        if (jsonSerializerNameHeader.Equals(default(KeyValuePair<string, StringValues>)))        {            await base.WriteResponseBodyAsync(context, selectedEncoding);            return;        }        var jsonFormatName = jsonSerializerNameHeader.Value.FirstOrDefault();        var response = context.HttpContext.Response;        using (var writer = context.WriterFactory(response.Body, selectedEncoding))        {            WriteObjectWithNamedSerializer(writer, jsonFormatName, context.Object);            await writer.FlushAsync();        }    }}

Then register it in your services.AddMvc

using System.Buffers;using Microsoft.AspNetCore.Mvc.Formatters;...services.AddMvc(options =>{    options.OutputFormatters.RemoveType<JsonOutputFormatter>();    options.OutputFormatters.Add(new NamedFormatJsonOutputFormatter(new JsonSerializerSettings(),        new Dictionary<string, JsonSerializerSettings>()        {            {                "pretty", new JsonSerializerSettings()                {                    Formatting = Formatting.Indented                }            }        }, ArrayPool<char>.Shared));});