在ASP.NET Core API应用程序中处理json pretty print param

时间:2017-05-12 14:09:44

标签: c# json asp.net-core asp.net-core-webapi

这个问题几乎是逐字逐句this stackoverflow question

但是我想在ASP.NET Core Api中完成它。我打算将它实现为头而不是查询字符串。我正在努力改变在ConfigureServices方法中设置的Json SerializerSettings。

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

我想要完成的是在我设置像X-MyApi-Pretty:false这样的标题时,将Serializer的设置更改为使用Formatting.None。

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

是否存在相应的问题,或者我只是认为这一切都错了? 我的google-fu真的让我失望了,我觉得我错过了一些非常明显的东西。

1 个答案:

答案 0 :(得分:4)

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

它的工作原理是读取一个名为“jsonformat”的标题,用于命名的json序列化器设置,例如名为“pretty”的设置。如果没有标头,或标头无效,则它将回退到默认的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));
});