现今大部分的app后端所提供的API都输出JSON格式的数据。在app客户端,程序员需要做一个JSON转模型的工作,以便更容易地使用数据。这个工作不只是说将JSON数据映射到模型上,还需要先把模型构建出来。
生成模型
有了一个具体的JSON,程序员通过观察和分析它,可以很容易地写出对应的模型。
例如对于如下简单的JSON:
{
"id": 42,
"name": "nixzhu"
}
我们可写出模型:
struct User {
let id: Int
let name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
init?(json: [String: Any]) {
guard let id = json["id"] as? Int else { return nil }
guard let name = json["name"] as? String else { return nil }
self.init(id: id, name: name)
}
}
这个模型包含了定义以及从JSON生成的初始化方法。它的代码行数比对应的JSON要多不少,如果是更复杂的JSON那写起来会更痛苦。
我们知道有一些第三方库,如SwiftyJSON,可以让我们比较容易地写初始化方法。但是,我们仍然还要自己去写模型的定义。
但如果我们使用Swift 4,利用其中的Codable协议,我们可写出:
struct User: Codable {
let id: Int
let name: String
}
它几乎和对应的JSON一样简单,而且我们不需要写从JSON生成的初始化方法,JSONDecoder会帮我们。这样,类似SwiftyJSON等第三方库也不再有使用的必要。
那有没有可能使用一个工具,从JSON中“推断”出一个模型呢?
稍微深入一点分析,我们会发现JSON里的信息足够多,比如属性的名字和类型。也许某个字符串表示的是一个URL,我们也有办法来分析一个字符串是否是一个URL,这样可以更合理地推断属性的类型。
还有一些问题需要考虑,比如数组类型的JSON。若它的各个Object的属性类型不一致,或者属性数量不一致,该怎么办?我们可能需要一个合并算法,而不能只是单单考虑数组的第一个Object。
另外,JSON可嵌套表示数据,我们的模型也需要嵌套定义。
从上面的分析可以看出,写一个从JSON生成模型的工具并不算一件简单的事情,要考虑的细节比较多。
所幸只需要一个人想到并写出这个工具就够了。下面正式介绍CuteBaby。
UI设计

如图所示,CuteBaby的界面分成三个部分,左边的侧栏可显示之前生成的模型,可以通过下面的按钮来新建一个条目。右上是JSON的输入框和配置板(它还可收起),而且JSON可以通过URL倒入,只需要粘贴URL即可。右下是Swift输出区域,也会输出一些提示信息。
整个界面非常简单,主要功能就是输入JSON(以及一些必要的配置),得到Swift模型。
具体功能罗列如下:
- 它能从JSON推断属性类型,如String、Int、Double、URL以及Date;
- 它能处理嵌套的JSON,并会生成嵌套的模型;
- 它支持Swift 4的Codable协议;
- 你还可通过Property Map指定属性名,通过Array Object Map指定数组內的对象名,通过Property Type Map指定属性类型,或通过Enum Properties为属性生成enum定义;
- 它亦能处理Array Root JSON,并会自动合并数组中对象的属性,且能判定是否需要可选值;
- 它能格式化JSON;
- 它还能从URL加载JSON;
- 最后,你还可通过Drag & Drop来拖动文本文件以创建新条目或修改当前条目的JSON。
配置选项
除了选择类型(struct或class),确定是否要public,或使用可变属性,或使用Codable。
你还可以通过Property Map来修改生成的属性名(有可能自动生成的不符合你的预期),或通过Array Object Map来指定数组內Object的名字,或通过Property Type Map指定某些属性的类型。
更进一步,你还可以通过Enum Properties指定某个属性为enum(可同时指定它的各case,或使用JSON內的信息自动生成)。
获取CuteBaby
欢迎从Mac App Store购买CuteBaby。
此外,你也可以使用它的开源命令行版本Baby,或者以Web界面呈现的Shared Baby。
如果它帮你节省了时间,我会非常高兴!😀💕
若有任何建议,欢迎在评论中说明。
