既定の構成を使用すると、System.Text.Json は object
型の値を、ポリモーフィズムを使用してシリアル化します。
object
用のカスタム コンバーターを登録すると、この動作の一貫性が低下します。
System.Text.Json
は従来、ルート レベルのオブジェクト値についてはポリモーフィズムをハードコーディングしていましたが、入れ子になったオブジェクト値の場合はそうではありませんでした。 .NET 7 以降では、カスタム コンバーターがポリモーフィズムを使用しないように、この動作が変更されました。
以前の動作
次のカスタム オブジェクト コンバーターについて考えます。
public class CustomObjectConverter : JsonConverter<object>
{
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
=> writer.WriteNumberValue(42);
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> throw new NotImplementedException();
}
以前のバージョンでは、次のコードは 0 としてシリアル化されました。 これは、シリアライザーがポリモーフィズムを使用し、カスタム コンバーターを無視したためです。
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object>(0, options);
一方、次のコードは、シリアライザーがカスタム コンバーターを優先するため、42 としてシリアル化されました。
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object[]>(new object[] { 0 }, options);
新しい動作
.NET 7 以降では、「以前の動作」セクションで定義されているカスタム オブジェクト コンバーターを使用すると、次のコードは 42 としてシリアル化されます。 これは、シリアライザーが常にカスタム コンバーターを参照し、ポリモーフィズムを使用しないためです。
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object>(0, options);
導入されたバージョン
.NET 7
破壊的変更の種類
この変更は、バイナリの互換性に影響を与える可能性があります。
変更理由
この変更が行われたのは、型がルート レベルの値または入れ子になった値としてシリアル化されるかどうかにより、型のシリアル化コントラクトが一貫しないためです。
推奨アクション
必要に応じて、型指定されていないシリアル化メソッドのいずれかを呼び出すことで、ルート レベルの値に対するポリモーフィズムに戻すことができます。
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize(0, inputType: typeof(int), options); // Serializes as 0.
影響を受ける API
- System.Text.Json.JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(Stream, TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(Utf8JsonWriter, TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.SerializeAsync<TValue>(Stream, TValue, JsonSerializerOptions, CancellationToken)
.NET