共用方式為


System.Text.Json 來源產生器後援

使用接受 JsonSerializerOptions 的其中一個 JsonSerializer 方法時,System.Text.Json 來源產生器將不再隱含地回復為無法辨識型別的反映型序列化。

先前的行為

請考慮 .NET 6 中的下列來源產生範例:

JsonSerializer.Serialize(new Poco2(), typeof(Poco2), MyContext.Default);

[JsonSerializable(typeof(Poco1))]
public partial class MyContext : JsonSerializerContext {}

public class Poco1 { }
public class Poco2 { }

因為 MyContext 不包含 Poco2 在其可序列化型別中,因此序列化會正確失敗,但發生下列例外狀況:

System.InvalidOperationException:

'Metadata for type 'Poco2' was not provided to the serializer. The serializer method used does not 
support reflection-based creation of serialization-related type metadata. If using source generation, 
ensure that all root types passed to the serializer have been indicated with 'JsonSerializableAttribute', 
along with any types that might be serialized polymorphically.

現在請考慮下列呼叫,其會嘗試使用 JsonSerializerOptions 來源產生器建構的執行個體,將相同的類型序列化 (MyContext):

JsonSerializer.Serialize(new Poco2(), MyContext.Default.Options);

選項執行個體會以無訊息方式將預設反映型合約解析程式納入為後援機制,因此類型會使用反映成功序列化。

相同的後援邏輯可針對附加至 JsonSerializerContext 的選項執行個體套用至 JsonSerializerOptions.GetConverter(Type)。 下列陳述式會使用內建反映轉換器傳回轉換器:

JsonConverter converter = MyContext.Default.Options.GetConverter(typeof(Poco2));

新的行為

從 .NET 7 開始,下列呼叫會失敗並與使用 JsonSerializerContext 多載時相同的例外狀況 (InvalidOperationException):

JsonSerializer.Serialize(new Poco2(), MyContext.Default.Options);

此外,下列陳述式將會失敗並顯示 NotSupportedException

JsonConverter converter = MyContext.Default.Options.GetConverter(typeof(Poco2));

導入的版本

.NET 7

中斷性變更的類型

這項變更會影響二進位相容性

變更原因

先前的行為違反最低意外原則,最終會破壞來源產生的目的。 使用可讓您自訂類型 JSON 序列化合約的功能版本,您就能夠微調合約中繼資料的來源。 請記住,以無訊息方式引進替代來源會變得更加不理想。

無論是刻意或是無意,您可能會視先前的行為而定。 建議的動作是更新您的 JsonSerializerContext 定義,使其包含所有類型的相依性:

[JsonSerializable(typeof(Poco1))]
[JsonSerializable(typeof(Poco2))]
public partial class MyContext : JsonSerializerContext {}

這可讓您的應用程式充分利用來源產生的優點,包括修剪安全性。

不過,在某些情況下,進行這類變更可能並不實用或也不太可能。 雖然不建議這麼做,但有幾種方式可讓您在來源產生的序列化程式中重新啟用反映後援。

使用自訂合約解析程式

您可以使用新的合約自訂功能來建置自訂合約解析程式,以在必要時回復為以反映為基礎的解析:

var options = new JsonSerializerOptions
{
     TypeInfoResolver = JsonTypeInfoResolver.Combine(MyContext.Default, new DefaultJsonTypeInfoResolver());
}

JsonSerializer.Serialize(new Poco2(), options); // Contract resolution falls back to the default reflection-based resolver.
options.GetConverter(typeof(Poco2)); // Returns the reflection-based converter.

使用 AppContext 參數

從 .NET 7 開始,您可以使用提供的 AppContext 相容性參數,全域重新啟用反映後援。 將下列項目新增至應用程式的專案檔,以重新啟用應用程式中所有來源產生內容的反映後援。 如需使用 AppContext 參數的詳細資訊,請參閱 .NET 執行時間組態設定的文章

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.EnableSourceGenReflectionFallback" Value="true" />
</ItemGroup>

受影響的 API