為什么我們有Node洞拨?(Why do we have Node?)
web是非常嚴(yán)格的烤礁,Swift是非常類型安全的讼积,這是在Swift進(jìn)行Web開發(fā)時(shí)的主要問題肥照。Node是我們?cè)噲D為這個(gè)問題提供解決方案。
什么是節(jié)點(diǎn)勤众?(What is Node?)
節(jié)點(diǎn)是一種數(shù)據(jù)抽象舆绎,重點(diǎn)是在不同類型之間建立中介。例如们颜,來自客戶端的json可能會(huì)使用節(jié)點(diǎn)在JSON和本身之間進(jìn)行轉(zhuǎn)換吕朵。
如何使用它?(How do I use it?)
如果您熟悉不那么類型安全的語(yǔ)言掌桩,那么Node可能會(huì)有一點(diǎn)不同边锁,讓我們看看幾個(gè)例子姑食,以及我們?nèi)绾伍_始在我們的項(xiàng)目中使用Node波岛。最常見的情況是,我們將使用節(jié)點(diǎn)轉(zhuǎn)換音半。
NodeInitializable
NodeInitializable可以被讀取和理解為An object that can be initialized with a Node
则拷。我們來看一個(gè)簡(jiǎn)單的實(shí)現(xiàn)。
struct Person: NodeInitializable {
let name: String
let age: Int
init(node: Node) throws {
name = try node.get("name")
age = try node.get("age")
}
}
現(xiàn)在我們有了這個(gè)曹鸠,我們就可以輕松地將抽象數(shù)據(jù)轉(zhuǎn)換成一個(gè)Person煌茬。以下是可能的樣子:
let person = try Person(node: json)
注意:對(duì)于JSON和數(shù)據(jù)庫(kù)行類型,有一些更高級(jí)的功能選項(xiàng)彻桃,我們稍后會(huì)介紹坛善。
通過讓我們的Person
對(duì)象繼承NodeInitializable
,我們還可以使用更高級(jí)的方法邻眷,如數(shù)組:
let people = try [Person](node: jsonArray)
NodeRepresentable
NodeRepresentable可以被讀取和理解為An object that can be represented as a Node
眠屎。我們來看看一個(gè)簡(jiǎn)單的實(shí)現(xiàn)。我們將繼續(xù)使用上面的Person
示例
extension Person: NodeRepresentable {
func makeNode(in context: Context) throws -> Node {
var node = Node(context)
try node.set("name", name)
try node.set("age", age)
return node
}
}
現(xiàn)在我們已經(jīng)做到了這一點(diǎn)肆饶,我們可以輕松地將我們person
或一組Person
對(duì)象轉(zhuǎn)換成一個(gè)Node
改衩。
let node = try person.makeNode(in: nil)
并且還用于集合,如數(shù)組
let node = try [kim, joe, jan].makeNode(in: nil)
環(huán)境(Context)
到目前為止驯镊,我們已經(jīng)看到很多Context
葫督,但是它是為了什么。當(dāng)我們序列化或映射對(duì)象時(shí)板惑,我們可能會(huì)有很多不同的情況橄镜,我們以不同的方式進(jìn)行映射。也許一個(gè)是數(shù)據(jù)庫(kù)冯乘,一個(gè)是視圖洽胶,一個(gè)是JSON等。
如果您使用Vapor往湿,我們提供了大量的環(huán)境和更多的本地集成選項(xiàng)妖异,但是這里可以定義自己的內(nèi)容惋戏。
import Node
final class MyContext: Context {
}
let myContext = MyContext()
extension Context {
var isMyContext: Bool {
return self is MyContext
}
}
現(xiàn)在我們的對(duì)象中,我們可以添加特殊的行為他膳。
extension Person: NodeRepresentable {
func makeNode(in context: Context) throws -> Node {
var node = Node(context)
try node.set("name", name)
try node.set("age", age)
if context.isMyContext {
try node.set("special-attribute", special)
}
return node
}
}
我們可以這樣調(diào)用:
let specialNode = person.makeNode(in: myContext)
這是一個(gè)常見的用法响逢,但可以適應(yīng)任何需要特殊元數(shù)據(jù)的場(chǎng)景,以幫助我們正確序列化或映射我們的對(duì)象棕孙。
NodeConvertible
NodeConvertible只是可代表和可初始化的組合舔亭。這些對(duì)象可以輕松地轉(zhuǎn)換到Node。從我們以前的Person對(duì)象中我們應(yīng)該能夠做到這一點(diǎn):
// ..
let node = person.makeNode(in: myContext)
let back = try Person(node: node)
print("\(person) went to node and back to \(back)")