将JsonSerializerSettings从JsonSerializer复制到新的JsonSerializer [英] Copy JsonSerializerSettings from JsonSerializer to new JsonSerializer

查看:98
本文介绍了将JsonSerializerSettings从JsonSerializer复制到新的JsonSerializer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么方法可以将设置从JsonSerializer类中删除,然后在新的JsonSerializer中重新实现它们?

Is there any way to take the settings out of a JsonSerializer class and reimplement them in a new JsonSerializer?

似乎没有任何方法可以做这样的事情.我发现的最好的方法是通过反射称为ApplySerializerSettings的私有方法.

There doesn't seem to be any methods to do anything like that. The best I found was a private method to be called through reflection, ApplySerializerSettings.

我正在尝试从WriteJson方法中获取序列化器,并将其复制到新的序列化器中,对其进行一些调整.具体来说,我想替换ContractResolver.

I'm trying to take the serializer from the WriteJson method and copy it into a new serializer, tweaking it a bit. Specifically I want to replace the ContractResolver.

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

推荐答案

似乎最好的方法是将所有设置复制到一个新对象中.其中有很多,所以这是一个很好的扩展方法(自8.0.3起).

Seems like the best way is to just copy all the settings into a new object. There are a ton of them, so here's a nice extension method to work with (as of 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;
  }
}

这很丑陋,但至少您只需要编写一次即可. 请稍加小心,因为属性本​​身不会被深度复制.

It's ugly, but at least you only have to write it once. Be slightly careful, as the properties themselves are not deep copied.

下面的答案取决于您的实施情况,尤其是在解决合同时.保持它以防万一,对某人有帮助.

Answer below is flaky depending on your implementation, especially when it comes to resolving a contract. Keeping it in just in case it helps someone.

因此,我无法完全复制设置,但是我发现可以考虑采用一种很好的解决方法.您可以在锁定的上下文中简单地设置要更改的属性,然后再重置它们.

So, I can't quite copy the settings, but I found a good work around that might want to be considered. You can simply set the properties you want to change, in a locked context, and then reset them afterward.

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.
}

这篇关于将JsonSerializerSettings从JsonSerializer复制到新的JsonSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆