在 ASP.NET 核心 API 应用程序中处理 json 漂亮的打印参数

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

这个问题几乎是在 this Whosebug question

上提出的问题

但我想在 ASP.NET 核心 Api 中进行。我计划将其实现为 header 而不是在查询字符串中。我正在努力更改已在 ConfigureServices 方法中设置的 Json SerializerSettings。

services.AddMvc(config =>
        {
            config.Filters.Add(new WebApiRequireHttps());                
        })
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.Formatting = Formatting.Indented;
            });

我想要完成的是将序列化程序的设置更改为在我设置 header 时使用 Formatting.None,例如 X-MyApi-Pretty: false。

我正在尝试像上述问题一样创建自己的 ActionFIlterAttribute。 Microsoft.AspNetCore.Mvc.Filters 使用 ActionExecutedContext,它似乎没有明显等同于 ActionContext.RequestContext.Configuration.Formatters.JsonFormatter。

是否有等同物,或者我只是在做这一切都错了? 我的 google-fu 在这方面真的让我失望了,我觉得我错过了一些非常明显的东西。

如果你希望它是全局的,你可以注册一个自定义输出格式化程序。这是我制作的一个工作示例。您可以免费使用。

它通过读取一个名为 "jsonformat" 的 header 来工作,用于一个名为 json 的序列化器设置,例如一个名为 "pretty" 的序列化器设置。如果 header 不存在,或者 header 无效,它会回退到默认的 json 序列化程序设置。如果您希望它在全球范围内可用,这可能是一种更简洁的方法——不需要操作过滤器。

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

然后在您的 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));
});