在Swift中,我们都会处理JSON、plist以及各种形式的[String: Any]
。Outlaw以声明性和类型安全的方式提供了处理这些数据的各种方式。Outlaw将帮助您使用面向协议编程™的力量来编写声明性、性能良好且错误处理的代码。
要使用Outlaw从[String: Any]
中提取值,就像下面这样:
let name: String = try json.value(for: "name")
let url: URL = try json.value(for: "user.website") // extract from nested objects!
通常,我们希望从一个可提取的对象(比如[String: Any]
)将其反序列化为我们本地模型之一——例如,我们可能希望用一些JSON初始化我们的本地模型之一。
struct User: Deserializable {
var id: Int
var name: String
var email: String
init(object: Extractable) throws {
id = try object.value(for: "id")
name = try object.value(for: "name")
email = try object.value(for: "email")
}
}
现在,只需提供简单的初始化器,您就可以直接从[String: Any]
中提取出您的模型!
let users: [User] = try json.value(for: "users")
很简单!感谢面向协议编程™!
我们已经看到了如何将我们的[String: Any]
转换到我们本地的模型中,但反过来怎么办呢?
extension User: Serializable {
func serialized() -> [String: Any] {
return {
"id": "id",
"name" : name,
"email": email
}
}
}
现在,您可能会想“但我不可以用反射来这么做吗?”您当然可以。如果您喜欢这么做,有一些其他优秀的框架可供您使用。但Outlaw认为反射可能会引导我们走向痛苦的世界。Outlaw生活在一个所见即所得™的世界里,您可以轻松地适应蛇形、驼峰或其他任何 Backend 开发者偏好的命名规范。Outlaw代码是显式的和声明性的。但不要光听Outlaw的说法,请阅读下面的文章在官方Swift博客上。
你不在乎错误吗?使用可选数据类型。
let users: [User]? = json.value(for: "users")
否则,用do-catch
包围您的代码,当出错时,您可以获得所有详细资料。
do {
let users: [User] = try json.value(for: "users")
}
catch {
print(error)
}
Outlaw默认支持提取原生的Swift类型,如String
、Int
等,以及URL
、Date
和符合Deserializable
的任何内容,以及所有这些数据类型的数组或字典。
然而,Outlaw 并不仅仅是让你陷入绝境!添加你自己的 Outlaw 值类型就像通过扩展你的类型使用 Value
一样简单。
extension CGPoint: Value {
public static func value(from object: Any) throws -> CGPoint {
guard let properties = object as? [String: CGFloat] else {
throw OutlawError.typeMismatch(expected: [String: CGFloat].self, actual: type(of: object))
}
let x: CGFloat = properties["x"] ?? 0
let y: CGFloat = properties["y"] ?? 0
return CGPoint(x: x, y: y)
}
}
只需简单实现 value(from:)
,Outlaw 就允许你立即执行此操作
let point: CGPoint = try json.value(for: "point")
面向协议编程™ 再次发挥作用!
不喜欢 Outlaw
实现的默认值提取?有不同的日期格式?没问题!在提取值时只需要一个转换函数即可。
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "GMT")
formatter.dateFormat = "MM/dd/yyyy"
let date: Date? = json.value(for: "date", with: { (dateString: String) -> Date? in
return formatter.date(from: dateString)
})
我们也可以利用 Swift 的能力,将以上代码缩短为
let date: Date? = json.value(for: "date", with: formatter.date)
Outlaw 基于与 Marshal 相同的底层代码,并且具有相同的高性能。你应始终以怀疑的态度看待基准测试,但无论如何,最好还是看一下这些基准测试 [链接]。不幸的是,JSONShootout 项目的构建方式使得 Outlaw 无法添加,因为与 Marshal 存在方法冲突。
Outlaw
是由 Marshal 的主要贡献者之一创建的。然而,Marshal
被设计成一个需要扩展以提供额外功能的简化框架。而 Outlaw
被设计成一个功能更丰富的框架,可以“开箱即用”地处理更多数据提取场景。