JsonMagic 一個(gè) Json 轉(zhuǎn) Model 的工具
JsonMagic 是 Mac 上用于將 Json 數(shù)據(jù)轉(zhuǎn)換成類定義代碼的應(yīng)用。轉(zhuǎn)換的代碼可以有多種,包括 Swift,Kotlin,Java。另外還支持將 Kotlin Model 轉(zhuǎn)換成 Swift Model。適合客戶端,Java 后端工程師,當(dāng)然如果自定義,只要有 Model 化需求的開發(fā)均可使用。
項(xiàng)目由個(gè)人使用 Swift 語(yǔ)言編寫,已開源。感興趣的碼友們可以 fork 改成適合自己的工具。代碼地址點(diǎn)我,里面有 DMG 文件,可以直接下載使用。
文章大綱如下:
- 應(yīng)用背景;
- 應(yīng)用特點(diǎn);
- 使用介紹;
- 代碼框架 & 用戶自定義輸出;
- 結(jié)語(yǔ);
應(yīng)用背景
應(yīng)用最大的初衷是減少軟件開發(fā)中將 Json 轉(zhuǎn)換為 Model 這個(gè)重復(fù)性且沒(méi)多少技術(shù)含量的工作時(shí)間,提升開發(fā)工作效率。程序猿工資在所有行業(yè)里不算低,上班時(shí)間寶貴。多出的時(shí)間咱們可以用來(lái)深入學(xué)學(xué)技術(shù)提升自我,亦或是純粹看NBA、刷B站,心情也是極好的。

Json model 化目的是使數(shù)據(jù)易于閱讀,便于處理。在應(yīng)用開發(fā)中十分常見(jiàn),最多的場(chǎng)景是將服務(wù)端數(shù)據(jù)轉(zhuǎn)換為客戶端便于使用的Model類。轉(zhuǎn)換內(nèi)容主要是兩個(gè)部分,一是將字典節(jié)點(diǎn)轉(zhuǎn)化為類,其次將字典內(nèi)的 key 值轉(zhuǎn)換為類的字段名,而字段的類型就是 key 對(duì)應(yīng)的 value 類型。
這個(gè)過(guò)程十分機(jī)械化,完全可用程序自動(dòng)轉(zhuǎn)換。在 iOS 平臺(tái)這方面的工具不多,且大多是命令行工具,對(duì)于習(xí)慣界面開發(fā)的同學(xué)來(lái)講不夠友好。安卓平臺(tái)卻有不少好用的工具,體驗(yàn)最好的是 Android Studio 插件。在 Android Studio 內(nèi)便可完成 Json 轉(zhuǎn) Model 的過(guò)程。
為什么還要自己搗鼓新的工具?

總結(jié):首先,對(duì)于 iOS 來(lái)說(shuō),沒(méi)有界面的友好的工具;
其次 iOS 和 Android 兩個(gè)平臺(tái)所有的工具對(duì)于 Json 數(shù)據(jù)的整理、容錯(cuò)能力不夠好。主要體現(xiàn)在逗號(hào),注釋:
-
逗號(hào)。數(shù)組內(nèi)最后一個(gè)對(duì)象后面的逗號(hào),或者對(duì)象內(nèi)最后一個(gè)屬性的逗號(hào),目前市面上的工具解析都會(huì)報(bào)錯(cuò)。
例如:以下例子無(wú)法正常生成{ "name": "zhang san", "address_list ": [ { "code": 12345, "receiver_name": "li si", "receiver_address": "北京市海淀區(qū)", }, ], "city_code": "010", }非法逗號(hào)出現(xiàn)的地方:
- address_list第一個(gè)元素的 },
- "receiver_address": "北京市海淀區(qū)",
- "city_code": "010",
-
注釋。JSON 數(shù)據(jù)有時(shí)候會(huì)被加上一些注釋便于閱讀,目前市面上的工具解析都會(huì)報(bào)錯(cuò)。
例如:以下例子無(wú)法正常生成{ "name": "zhang san", "address_list ": [ { // 地址編碼 "code": 12345, "receiver_name": "li si", // 接受者名稱 "receiver_address": "北京市海淀區(qū)" // 接受者地址 } ], "city_code": "010" // 城市代碼 }
而 JsonMagic 就是要解決這兩個(gè)問(wèn)題。
應(yīng)用特點(diǎn)
JsonMagic 特點(diǎn)總結(jié)如下:
- 常見(jiàn)非法逗號(hào)容錯(cuò);
- 規(guī)范注釋容錯(cuò);
- iOS & Android 統(tǒng)一化。集成 iOS 和 Android 兩個(gè)平臺(tái)的轉(zhuǎn)換工作。支持轉(zhuǎn) Swift 代碼,Kotlin 代碼,Java 代碼。還支持 Kotlin Model 轉(zhuǎn)換成 Swift Model;
- 自定義轉(zhuǎn)換能力。代碼開源,且將 JSON 抽象化,開發(fā)者只需要關(guān)心最后的轉(zhuǎn)換部分;
- Kotlin 可選擇的注解。可勾選是否
SerializedNameorJsonProperty;
使用介紹
應(yīng)用啟動(dòng)后,界面如下圖:

中間比較大的區(qū)域,左邊是用戶輸入的 Json 數(shù)據(jù),右邊是生成的 Model 數(shù)據(jù)。
其他操作部分,分為五大塊,按照標(biāo)的數(shù)字:
- 選擇需要轉(zhuǎn)換的代碼,默認(rèn)是 Swift。Json to Swift, Json to Kotlin...;
- 可以指定后綴,默認(rèn)是 Model;需要填入 Model 的名稱,不帶后綴的;
- 點(diǎn)擊 Run 就開始生成,生成的代碼在 Model大框內(nèi)。成功與失敗的狀態(tài)會(huì)在底部展示;
- 對(duì)結(jié)果的操作。比如
Copy Model拷貝到剪切板。后者是生成文件; - 如果想看解析的過(guò)程,可以點(diǎn)擊Log按鈕,會(huì)有彈窗;
成功狀態(tài)圖示:

未填 Model 名稱失敗狀態(tài)圖示:

有多余注釋,逗號(hào)但解析成功狀態(tài)圖示:

代碼架構(gòu) & 自定義 Model 化
Json化的代碼主要分為三個(gè)過(guò)程,如圖:

首先對(duì) Json 進(jìn)行預(yù)處理,檢查必要的輸入,移除注釋等;
-
其次將 Json 轉(zhuǎn)換為自定義的對(duì)象,使用
Jsonic.DataType保存;internal indirect enum DataType: Equatable { static func == (lhs: Jsonic.DataType, rhs: Jsonic.DataType) -> Bool { return lhs.swiftDescription == rhs.swiftDescription } case string, int, long, double, bool, unknown case array(itemType: DataType) case object(name: String, properties: [PropertyDefine]) ... -
最后根據(jù)不同的生成類型,生成不同的輸出代碼;
public enum OutputType { public struct KotlinConfig { /// should output SerializedName var isSerializedNameEnable: Bool /// should output JsonProperty var isJsonPropertyEnable: Bool } case swift case kotlin(config: KotlinConfig) case java ...
自定義輸出
從整體架構(gòu)來(lái)看,自定義輸出只需要關(guān)心最后一步 Output。只需要兩步:
- 增加一種 OutputType 類型;
- 定義 class 與 property 輸出;
是不是比把大象放進(jìn)冰箱簡(jiǎn)單一些~

以轉(zhuǎn) Swift 舉例:
第一步,增加 Swift 類型:
public enum OutputType {
...
case swift
case kotlin(config: KotlinConfig)
case java
...
第二步,增加自定義 model 轉(zhuǎn)換代碼:
fileprivate func modelDescription(item: Jsonic.DataType) -> String? {
guard case let Jsonic.DataType.object(name, properties) = item else { return nil }
switch self {
...
case .swift:
return swiftObjectDesc(name: name, properties: properties)
...
}
}
private func swiftObjectDesc(name: String, properties: [Jsonic.PropertyDefine]) -> String {
var text = "class \(name): Codable {\n"
for property in properties {
text += " var \(property.name): \(property.type.swiftDescription)?\n"
}
text += "}"
return text
}
最后
幾年前自己也是用的命令行(Python)來(lái)轉(zhuǎn)換 Model,最近剛好契機(jī)將其界面化,并且使用 Swift 代碼進(jìn)行重寫。代碼可能會(huì)有 bug,大家可多多留言,我會(huì)盡快修復(fù)。當(dāng)然各位碼友也可以 fork 后自己升級(jí)改動(dòng),不過(guò)還是希望有問(wèn)題能夠反饋,這樣能夠幫助到更多的同學(xué)。Happy Coding~
