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

流过昼夜 提交于 2019-12-24 07:31:03

问题


ASP.Net Core 2.2 allows to set serializer settings using MvcJsonOptions.SerializerSettings property. The problem is that it affects both input and output. Is there a way to have separate options for input (deserialization) and output (serialization)? In particular, I need to set a different behavior for NullValueHandling settings: ignore null errors for non-nullable fields when deserializing client json but keep nulls for defined model fields when serializing the result.

For example, I have a C# model for request:

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

And input JSON: { id: null, parentId: null, name: "test" }. The deserialization fails for NullValueHandling.Include but works for NullValueHandling.Ignore.

But when I serialize an entity like this one

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

It keeps null with NullValueHandling.Include: { id: 1, parentId: null, name: "test" } but erases it with NullValueHandling.Ignore: { id: 1, name: "test" }.

I need to achieve the "Ignore" scenario for input and "Include" for output.


回答1:


Finally found this workaround: 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));
    }
}

and

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

in service provider configuration




回答2:


I would use JsonSerializerSettings class from Newtonsoft.Json to define two instances mySerializeSetting and myDeserializeSettings.

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

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

To deserialize:

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

To see how to set up serialization settings see https://www.newtonsoft.com/json/help/html/SerializationSettings.htm



来源:https://stackoverflow.com/questions/59107392/asp-net-core-2-2-separate-serializer-settings-for-input-and-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!