ASP.Net Core 2.2 - 输入和输出的独立序列化器设置

ASP.Net Core 2.2 - separate serializer settings for input and output

ASP.Net Core 2.2 允许使用 MvcJsonOptions.SerializerSettings 属性 设置序列化器设置。问题是它会影响输入和输出。有没有办法为输入(反序列化)和输出(序列化)提供单独的选项?特别是,我需要为 NullValueHandling 设置设置不同的行为:在反序列化客户端 json 时忽略不可为 null 的字段的 null 错误,但在序列化结果时为定义的模型字段保留 null。

比如我有一个C#模型请求:

public class SomeEntity
{
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public string Name { get; set; }
}

并输入JSON:{ id: null, parentId: null, name: "test" }NullValueHandling.Include 的反序列化失败但适用于 NullValueHandling.Ignore.

但是当我序列化这样一个实体时

new SomeEntity
{
    Id = 1,
    ParentId = null,
    Name = "test"
}

它用 NullValueHandling.Include 保持空值:{ id: 1, parentId: null, name: "test" } 但用 NullValueHandling.Ignore 擦除它:{ id: 1, name: "test" }.

我需要实现 "Ignore" 输入场景和 "Include" 输出场景。

我会使用 Newtonsoft.Json 中的 JsonSerializerSettings class 来定义两个实例 mySerializeSettingmyDeserializeSettings

using Newtonsoft.Json;
using Microsoft.Rest.Serialization;

string requestContent = SafeJsonConvert.SerializeObject(value, mySerializationSettings);

要反序列化:

var result = SafeJsonConvert.DeserializeObject<myclass>(input, myDeserializeSettings);

要了解如何设置序列化设置,请参阅 https://www.newtonsoft.com/json/help/html/SerializationSettings.htm

终于找到了解决方法:https://github.com/aspnet/Mvc/issues/4562#issuecomment-226100352

public class CustomSerializerSettingsSetup : IConfigureOptions<MvcOptions>
{
    private readonly ILoggerFactory _loggerFactory;
    private readonly ArrayPool<char> _charPool;
    private readonly ObjectPoolProvider _objectPoolProvider;

    public CustomSerializerSettingsSetup(
        ILoggerFactory loggerFactory,
        ArrayPool<char> charPool,
        ObjectPoolProvider objectPoolProvider)
    {
        _loggerFactory = loggerFactory;
        _charPool = charPool;
        _objectPoolProvider = objectPoolProvider;
    }

    public void Configure(MvcOptions options)
    {
        options.OutputFormatters.RemoveType<JsonOutputFormatter>();
        options.InputFormatters.RemoveType<JsonInputFormatter>();
        options.InputFormatters.RemoveType<JsonPatchInputFormatter>();

        var outputSettings = new JsonSerializerSettings();
        options.OutputFormatters.Add(new JsonOutputFormatter(outputSettings, _charPool));

        var inputSettings = new JsonSerializerSettings();
        var jsonInputLogger = _loggerFactory.CreateLogger<JsonInputFormatter>();
        options.InputFormatters.Add(new JsonInputFormatter(
            jsonInputLogger,
            inputSettings,
            _charPool,
            _objectPoolProvider));

        var jsonInputPatchLogger = _loggerFactory.CreateLogger<JsonPatchInputFormatter>();
        options.InputFormatters.Add(new JsonPatchInputFormatter(
            jsonInputPatchLogger,
            inputSettings,
            _charPool,
            _objectPoolProvider));
    }
}

services.TryAddEnumerable(
    ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, CustomSerializerSettingsSetup>());

在服务提供商配置中