【文章內容使用 Gemini 1.5 Pro 自動翻譯產生】
Dart 的 built_value 序列化功能
上週我介紹了使用 built_value 建立不可變物件模型。我們看到了如何在 built_value 中定義物件模型;它們是不可變的,易於使用,而且,如果您喜歡這種東西,會有很多樂趣。
本文涵蓋了 built_value 套件的其餘部分。最大的項目是,正如您可能從標題中猜到的那樣,它們也是可序列化的。
以下是 built_value 序列化的使用方法:
1 | // 使用 built_value 定義的值類型。 |
注意到「JSON.encode」了嗎?序列化器實際上並沒有序列化為字串;而是轉換為 Dart 內建的 JSON 序列化知道如何處理的原始類型。因此,如果您願意,可以使用 JSON 以外的其他格式。
您可能認為序列化應該「正常工作」,但其中涉及一些微妙的權衡。讓我們深入研究 built_value 的序列化。
多型性
built_value 序列化的最重要的一個方面是它支援多型性。具體來說,您可以擁有抽象類型的欄位,並且
- 該抽象類型的任何可序列化實作都可以被序列化;
- 足夠的資訊將被寫入網路,以便反序列化為正確的類型。
最簡單的例子是它可以序列化一個 Object 列表:
1 | serializers.serialize(BuiltList<Object>([1, 'two', 3])); |
僅在反序列化時需要消除歧義時,才會在網路上加入額外資訊。因此,如果您有一個類型為「BuiltList
底線是您可以隨意定義您的物件模型,built_value 將對其進行序列化。如果您想更詳細地了解這一點,map 序列化器測試 探索了所有可能性。
多種實作
所有序列化機制都必須面對的另一個問題是以某種方式定義可序列化類型的範圍。這裡 built_json 做了一些不尋常的事情,允許一個「類型」的多種實作。
這是可行的,因為類型在網路上是僅透過其類別名稱來定義的。例如,沒有嘗試區分不同的名為「Login」的類別;假設發送方和接收方都有一個名為「Login」的類別的相容序列化器可用。
這增加了有用的靈活性。例如,如果您在伺服器和客戶端上使用 Dart,那麼您可以在物件模型中為每個類別進行選擇:
- 您可以在客戶端和伺服器上使用相同的類別。
- 或者,您可以使用不同的類別。這些實作必須具有相同的名稱和相容的欄位。
例如,您可以為客戶端擁有一個處理渲染和解析的「Login」類別;以及為伺服器擁有一個處理驗證和資料庫的單獨的「Login」類別。當然,僅限伺服器的實作可以自由使用「dart:io」等套件,僅限客戶端的實作可以使用「dart:html」等套件。
多種語言
由於 built_value 序列化僅透過類別名稱來識別類型,因此序列化資料可以很好地映射到任何物件導向語言。透過 AutoValue 計劃支援 Java。
多個版本
序列化 built_value 資料以一種非常簡單的方式向後/向前相容:它依賴於類別名稱和欄位名稱。類別名稱變更和必要的欄位名稱變更會導致不相容。
可為空的欄位更靈活:在序列化時,只有在非空時才會寫入它們;在反序列化時,如果找不到它們,則預設為空。因此,可以加入、移除或重新命名可為空的欄位,這不是一個不相容的變更。
無法辨識的欄位將被忽略。
無反射
最後,對於效能至關重要的一點是,built_value 不以任何形式使用反射。所有分析都在程式碼生成時完成,為您留下最少、高效能的序列化程式碼。
這就是使用 built_value 進行序列化。您可以坐下來編寫物件模型,它可以直接序列化以用於 RPC 或長期儲存。
EnumClass
最後,built_value 還附帶一個功能:EnumClass。Dart 列舉不是類別,但一個強大的物件模型需要像類別一樣運作的列舉。顯而易見的模式是建立一個帶有「static const」欄位的類別,而 EnumClass 使這更容易做到。它提供:
- 為「values」和「valueOf」生成的程式碼。
- 透過 built_value 序列化器進行序列化。
- 給 Angular 或 Angular2 使用者的額外獎勵:程式碼生成可以選擇性地生成一個 mixin,以幫助您在模板中使用列舉。
所有這些功能都可以在範例 中看到。
本週就到這裡了!在介紹了 built_value 的基礎知識之後,我準備在下週詳細介紹聊天範例。敬請關注!
編輯:下一篇文章。
Dart 的 built_value 序列化功能 最初發佈在 Medium 的 dartlang 上,人們在那裡透過突出顯示和回應這個故事來繼續討論。