本文說明反映與來源產生之間的差異,因為它與 System.Text.Json 串行化有關。 它也提供如何為您的案例選擇最佳方法的指引。
元數據集合
若要序列化或還原序列化類型,JsonSerializer 需要有關如何存取型別成員的資訊。
JsonSerializer 需要下列資訊:
- 如何存取屬性取值器和欄位以進行序列化。
- 如何存取反序列化的建構函式、屬性設定器和欄位。
- 有關用來自定義序列化或反序列化的屬性的信息。
- 執行時配置來自 JsonSerializerOptions。
這項資訊稱為 元數據。
反射
預設情況下,透過 JsonSerializer反射在執行時收集元資料。 每當 JsonSerializer 第一次必須序列化或反序列化某類型時,它會收集並快取此元數據。 元數據收集程式需要時間並使用記憶體。
源代碼生成
作為替代方式,System.Text.Json 也可以使用 C# 來源產生功能來改善效能、減少私人記憶體用量,以及輔助組件調整,以降低應用程式大小。 此外,某些反映 API 無法在 原生 AOT 應用程式中使用,因此您必須針對這些應用程式使用來源產生。
來源產生可用於兩種模式:
元數據型模式
在編譯期間,收集串行化所需的資訊,
System.Text.Json併產生原始碼檔案,以填入所要求類型的 JSON 合約元數據。串行化優化 (快速路徑) 模式
JsonSerializer 自定義串行化輸出的功能,例如命名原則和參考保留,會產生效能額外負荷。 在串行化優化模式中,System.Text.Json 產生優化的串行化代碼,直接使用
Utf8JsonWriter。 此優化或 快速路徑程式 程式碼會增加序列化吞吐量。目前無法使用快速路徑 反序列化 。 如需詳細資訊,請參閱 dotnet/runtime 問題 55043。
System.Text.Json 的來源產生需要 C# 9.0 或更新版本。
Note
F# 歧視工會支援僅在反射模式下有效。 它需要動態程式碼和未修剪的反射元資料。 你無法將它與原始碼生成或 Native AOT 一起使用。 欲了解更多資訊,請參閱 F# 歧視工會。
功能比較
根據每個模式所提供的下列優點,選擇反映或來源產生模式:
| 優點 | 反射 | 源代碼生成 (元數據型模式) |
源代碼生成 (串行化優化模式) |
|---|---|---|---|
| 程式代碼更簡單。 | ✔️ | ❌ | ❌ |
| 偵錯更簡單。 | ❌ | ✔️ | ✔️ |
支援在非公用成員上使用 [JsonInclude]。 |
✔️ | ✔️* | ✔️* |
| 支援所有可用的串行化自定義。 | ✔️ | ❌ † | ❌ † |
| 減少啟動時間。 | ❌ | ✔️ | ✔️ |
| 減少私人記憶體使用量。 | ❌ | ✔️ | ✔️ |
| 消除了運行時反射。 | ❌ | ✔️ | ✔️ |
| 促使安全修剪應用程式大小的縮減。 | ❌ | ✔️ | ✔️ |
| 增加串行化輸送量。 | ❌ | ❌ | ✔️ |
* 從 .NET 11 開始,原始碼產生功能支援你以 [JsonInclude] 明確標記的 private、internal 和 protected 成員。 它也支援對你以 internal 標記的屬性使用 private、protected 和 [JsonInclude] 存取子。 基於元資料的原始碼產生支援不可存取的建構器,並用 [JsonConstructor] 標記這些建構器。 產生的 setter 只會對 JSON 中出現的僅限 init 的屬性執行,因此省略的屬性會保留其初始設定值。 在 .NET 10 和更早版本中,原始碼產生不支援 private 或 protected 成員或存取子,也不支援無法存取的建構函式。 產生的上下文只有在成員與存取者共用一個組件時才能存取 internal 。 欲了解更多資訊,請參閱 私人會員與製造商。
† 使用合約自訂 API 來修改原始碼產生的合約。