有没有办法从JsonSerializer
课程中取出设置,并在新的JsonSerializer
中重新实现这些设置?
似乎没有任何方法可以做任何类似的事情。我找到的最好的是通过反射调用的私有方法ApplySerializerSettings
。
我正在尝试从WriteJson
方法中获取序列化程序并将其复制到新的序列化程序中,稍微调整一下。具体来说,我想替换ContractResolver
。
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
答案 0 :(得分:8)
似乎最好的方法是将所有设置复制到新对象中。它们有很多,所以这里有一个很好的扩展方法(从8.0.3开始)。
public static class JsonSerializerExtensions
{
public static JsonSerializer DeepCopy(this JsonSerializer serializer)
{
var copiedSerializer = new JsonSerializer
{
Context = serializer.Context,
Culture = serializer.Culture,
ContractResolver = serializer.ContractResolver,
ConstructorHandling = serializer.ConstructorHandling,
CheckAdditionalContent = serializer.CheckAdditionalContent,
DateFormatHandling = serializer.DateFormatHandling,
DateFormatString = serializer.DateFormatString,
DateParseHandling = serializer.DateParseHandling,
DateTimeZoneHandling = serializer.DateTimeZoneHandling,
DefaultValueHandling = serializer.DefaultValueHandling,
EqualityComparer = serializer.EqualityComparer,
FloatFormatHandling = serializer.FloatFormatHandling,
Formatting = serializer.Formatting,
FloatParseHandling = serializer.FloatParseHandling,
MaxDepth = serializer.MaxDepth,
MetadataPropertyHandling = serializer.MetadataPropertyHandling,
MissingMemberHandling = serializer.MissingMemberHandling,
NullValueHandling = serializer.NullValueHandling,
ObjectCreationHandling = serializer.ObjectCreationHandling,
PreserveReferencesHandling = serializer.PreserveReferencesHandling,
ReferenceResolver = serializer.ReferenceResolver,
ReferenceLoopHandling = serializer.ReferenceLoopHandling,
StringEscapeHandling = serializer.StringEscapeHandling,
TraceWriter = serializer.TraceWriter,
TypeNameHandling = serializer.TypeNameHandling,
SerializationBinder = serializer.SerializationBinder,
TypeNameAssemblyFormatHandling = serializer.TypeNameAssemblyFormatHandling
};
foreach (var converter in serializer.Converters)
{
copiedSerializer.Converters.Add(converter);
}
return copiedSerializer;
}
}
这很难看,但至少你只需要写一次。 要小心,因为属性本身不会被深层复制。
根据您的实施,下面的答案是不稳定的,特别是在解决合同时。保持它,以防它有助于某人。
所以,我无法完全复制设置,但我找到了一个可能需要考虑的好工作。您可以在锁定的上下文中设置要更改的属性,然后在之后重置它们。
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var thing = value as IThing;
if (thing == null)
throw new ArgumentException($"Writing Json failed because " +
"value was not a 'Thing' of type, {typeof(IThing).FullName}");
JObject jsonThing;
//If your solution is multithreaded,
//and is using a shared serializer (which you probably are),
//you should lock the serializer so that it doesn't accidentally use
//the "CustomObjectResolver"
lock (serializer)
{
//Hold the original value(s) to reset later
var originalContractResolver = serializer.ContractResolver;
//Set custom value(s)
serializer.ContractResolver = new CustomObjectResolver();
//Serialization with custom properties
jsonThing = JObject.FromObject(value, serializer);
//Reset original value(s)
serializer.ContractResolver = originalContractResolver;
}
//Finish serializing and write to writer.
}
答案 1 :(得分:3)
不确定这是否是主题-但这是我在Google中搜索 Clone JSONSerializerSettings 时出现的第一篇文章,我想我会留个通知。
我刚刚有一个类似的要求。
在我的.Net Core WebApi解决方案中,我们有使用
序列化JSON的默认设置jsonSerializaerSettings.NullValueHandling = NullValueHandling.Ignore;
但是在一些端点中,我也想序列化null属性,因为这些端点代表一个数据集。因此,所有对象在序列化时都应具有所有属性。
我尝试了几种方法,然后阅读了Options模式,偶然发现了IOptionSnapshot-https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1#reload-configuration-data-with-ioptionssnapshot
所以我最终将IOptionsSnapshot注入到我的控制器方法中,这为我提供了默认选项的副本,我可以修改该默认选项并将其用于单个请求。
并在下一个请求时,注入的选项恢复为默认值。
好又容易-至少出于我的目的。
所以我样品的最终解决方案是这样
[HttpPost("dataset", Name = "GetReportDataset")]
public IActionResult GetReportDataset(
[FromServices]IOptionsSnapshot<MvcJsonOptions> jsonOptions,
[FromBody]DataSetReport report,
[FromQuery]int? top)
{
//Logic to fetch dataset
var myDataSet = myRepository.GetDataset(report, top);
var serializerSettings = jsonOptions.Value.SerializerSettings;
serializerSettings.NullValueHandling = NullValueHandling.Include;
return new JsonResult(myDataSet, serializerSettings);
}
希望这可以帮助其他人来这里使用类似的东西。
/安德斯