JsonSerializerSettings を JsonSerializer から新しい JsonSerializer にコピーする 質問する

JsonSerializerSettings を JsonSerializer から新しい JsonSerializer にコピーする 質問する

クラスから設定を取り出しJsonSerializer、新しいクラスで再実装する方法はありますかJsonSerializer?

そのようなことを行う方法はないようです。私が見つけた最良の方法は、リフレクションを通じて呼び出されるプライベート メソッドでしたApplySerializerSettings

メソッドからシリアライザーを取得しWriteJsonて新しいシリアライザーにコピーし、少し調整しようとしています。具体的には、 を置き換えたいですContractResolver

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

ベストアンサー1

最善の方法は、すべての設定を新しいオブジェクトにコピーすることのようです。設定はたくさんあるので、ここでは便利な拡張メソッドを紹介します (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.
}

おすすめ記事