在 Swift 中,我们经常需要处理 JSON、plist 以及各种形式的 [String: Any]
数据。Marshal
相信,您无需具备单子或魔镜方面的博士学位,也能以一种富有表现力且类型安全的方式来处理这些数据。Marshal
将利用面向协议编程™ 的强大功能,帮助您编写声明式、高性能、具备错误处理的代码。
使用 Marshal 从 [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: Unmarshaling {
var id: Int
var name: String
var email: String
init(object: MarshaledObject) 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")
这太简单了!感谢面向协议编程™!
您是不顾一切的那种人,不在乎错误吗?使用 try?
给自己一个可选值。 否则,请加入我们这些守法的人,并将您的代码封装在 do-catch
中,以便在出现问题时获取所有有用的详细信息。
Marshal
开箱即用地支持提取 Swift 原生类型(如 String
、Int
等)、URL
、任何符合 Unmarshaling
协议的类型,以及上述所有类型的数组。 它不支持提取更复杂的类型,如 Date
,因为日期格式种类繁多等等。
但是,Marshal 不会让你束手无策! 添加你自己的 Marshal 值类型就像用 ValueType
扩展你的类型一样简单。
extension Date : ValueType {
public static func value(from object: Any) throws -> Date {
guard let dateString = object as? String else {
throw MarshalError.typeMismatch(expected: String.self, actual: type(of: object))
}
// assuming you have a Date.fromISO8601String implemented...
guard let date = Date.fromISO8601String(dateString) else {
throw MarshalError.typeMismatch(expected: "ISO8601 date string", actual: dateString)
}
return date
}
}
只需实现 value(from:)
,Marshal 就能让您立即做到这一点:
let birthDate: Date = json.value(for: "user.dob")
面向协议编程™ 再次奏效!
我们已经研究了如何从 [String: Any]
转换为本地模型,但反过来又如何呢?
extension User: Marshaling {
func marshaled() -> [String: Any] {
return {
"id": id,
"name" : name,
"email": email
}
}
}
现在,您可能会想“但是我不能使用反射来自动执行此操作吗?” 你可以。 如果你喜欢那样,有一些其他的优秀框架供你使用。 但是 Marshal 认为镜像可能会导致困境。 Marshal 活在一个所见即所得™ 的世界中,您可以轻松地适应 snake case、camel case 或后端开发人员喜欢的任何 case 的 API。 Marshal 代码是显式且声明式的。 但不要只相信 Marshal 的话 —— 阅读官方 Swift 博客上的 这篇文章的结尾。
当然,如果 Marshal 没有最快的执行速度,它就不会成为 Marshal。 您应该始终以怀疑的态度对待基准测试,但还是先看看 这些基准测试吧。
Marshal
最初是 Jason Larsen 关于 JSON 解析的博客系列,但很快演变成一个社区项目。 特别感谢许多人,他们在不同程度上贡献了想法和代码。 其中一些人,按字母顺序排列: