Flutter如何更便捷的json轉model

小和山吳彥祖發表於2020-06-17

0x1 前言

作為剛開始接觸flutter的iOS開發,json轉模型這部分一直是我非常頭疼的地方。現在網上能找到的方案一般有兩種

0x11 通過解析json建立模型檔案

flutter裡把反射直接禁掉了,這直接導致我們不能動態的給模型賦值。我們需要建立一個又一個的fromJson方法,然後在這個方法裡取出一個又一個的資料賦值給模型。這是一部分重複且非常無聊程式碼。這種方式在使用的工程中也存在一系列的問題:

  • 不符合我們正常的開發習慣,一般我們拿到的都是介面欄位定義,與之相對應的json檔案我們是沒有的,構建一個json檔案這裡又無端加了一部分工作量。
  • 沒法對於資料做一些容錯處理,在做舊業務遷移改造的時候這方面的問題會暴露出來,讓人抓狂。
  • 後續新增刪除欄位比較麻煩

工具地址

Flutter如何更便捷的json轉model

0x12 json_serializable

json_serializable用到了dart裡的註解來自動生成程式碼。關於註解你可以類比是編譯外掛,在預編譯的時候解析出模型裡定義的欄位,然後根據這些欄位建立與之相對應的fromJson方法。這種方式和上面的方案某些層面很相似,但是又在一定程度上解決了上面提到的一些問題:

  • 更加符合我們的開發習慣,根據介面欄位定義屬性。
  • 通過指令碼生成程式碼,新增刪除欄位更加方便。

還存在的問題:

  • 還是沒法對資料做容錯處理。
  • 還是存在一些需要手動新增的重複程式碼,如下紅框中的程式碼。

Flutter如何更便捷的json轉model

0x2 更加便捷的方案

我們先來梳理一下iOS裡YYModel之類的框架是怎麼做json自動轉model的。首先通過runtime解析出定義的所有屬性名、屬性的型別。然後用這些屬性名去json裡取值賦值給model。那麼我們如果想要做一套類似的庫的話我們需要如下能力

0x21 解析出模型裡所有屬性名、屬性型別

flutter把dart裡的反射禁掉了,指望系統的api肯定是不現實了。我們比較容易想到的是我們可以手動輸出這部分內容到一個全域性的map裡。要用的時候通過className去map裡取。手動做肯定不現實,這部分的資料是有規律性的,所以通過指令碼來做非常合適。你研究過json_serializable的實現的話你一定知道註解。我們可以用註解或者自定義builder來走一個預編譯,在這個階段我們能解析類,獲取引數名、引數型別。解析出這部分資料之後建立一個檔案,然後把這些解析出來的資料根據特定的格式輸出一個全域性的map到剛才建立的檔案裡。我這邊不聊具體實現,只聊方案。具體註解相關的使用可以看註解相關資料

0x22 動態建立物件

通過上面的步驟我們能解析出屬性的型別、屬性名。對於自定義的物件來說,就會存在一個根據類名來建立對應物件的需求。通過閉包來建立物件,用className做key閉包做value,然後把這邊分資料也放到上一步解析出來的map裡。

className : () => className()
複製程式碼

0x23 動態賦值

動態建立完物件之後我們需要能給這個物件的屬性來動態賦值。和之前建立物件的處理方式類似,我們也可以通過閉包來做,我們輸出如下格式的內容到上面的map中

name : (dynamic instance, value) => instance.name = value
複製程式碼

0x24 動態取值

在做model to json功能的時候我們需要能夠通過一個String格式的name去物件裡動態獲取這部分的資料。和上面用閉包來處理類似。我們需要輸出如下格式的內容到之前的map中

name : (dynamic instance) => instaned.name
複製程式碼

0x25 大致流程圖

Flutter如何更便捷的json轉model

0x3 hn_easy_model

我這邊已經實現了一套框架,配置完之後使用起來成本極低,對於客戶端轉過來寫flutter的同學也更友好。框架地址,歡迎大家試用。

相關文章