问题
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