Mapper
Mapper 是一个简单的 Swift 库,可以将 JSON 转换为强类型对象。相比其他一些库,Mapper 的一个优势是可以有不可变属性。
安装
使用 CocoaPods
use_frameworks!
pod "ModelMapper"
使用 Carthage
github "lyft/mapper"
使用说明
简单示例
import Mapper
// Conform to the Mappable protocol
struct User: Mappable {
let id: String
let photoURL: URL?
// Implement this initializer
init(map: Mapper) throws {
try id = map.from("id")
photoURL = map.optionalFrom("avatar_url")
}
}
// Create a user!
let JSON: NSDictionary = ...
let user = User.from(JSON) // This is a 'User?'
与枚举一起使用
enum UserType: String {
case Normal = "normal"
case Admin = "admin"
}
struct User: Mappable {
let id: String
let type: UserType
init(map: Mapper) throws {
try id = map.from("id")
try type = map.from("user_type")
}
}
Mappable
对象
嵌套 struct User: Mappable {
let id: String
let name: String
init(map: Mapper) throws {
try id = map.from("id")
try name = map.from("name")
}
}
struct Group: Mappable {
let id: String
let users: [User]
init(map: Mapper) throws {
try id = map.from("id")
users = map.optionalFrom("users") ?? []
}
}
Convertible
来透明地将其他类型从 JSON 转换过来
使用 extension CLLocationCoordinate2D: Convertible {
public static func fromMap(_ value: Any) throws -> CLLocationCoordinate2D {
guard let location = value as? NSDictionary,
let latitude = location["lat"] as? Double,
let longitude = location["lng"] as? Double else
{
throw MapperError.convertibleError(value: value, type: [String: Double].self)
}
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
}
struct Place: Mappable {
let name: String
let location: CLLocationCoordinate2D
init(map: Mapper) throws {
try name = map.from("name")
try location = map.from("location")
}
}
let JSON: NSDictionary = [
"name": "Lyft HQ",
"location": [
"lat": 37.7603392,
"lng": -122.41267249999999,
],
]
let place = Place.from(JSON)
自定义转换
private func extractFirstName(object: Any?) throws -> String {
guard let fullName = object as? String else {
throw MapperError.convertibleError(value: object, type: String.self)
}
let parts = fullName.characters.split { $0 == " " }.map(String.init)
if let firstName = parts.first {
return firstName
}
throw MapperError.customError(field: nil, message: "Couldn't split the string!")
}
struct User: Mappable {
let firstName: String
init(map: Mapper) throws {
try firstName = map.from("name", transformation: extractFirstName)
}
}
解析嵌套或整个对象
struct User: Mappable {
let name: String
let JSON: AnyObject
init(map: Mapper) throws {
// Access the 'first' key nested in a 'name' dictionary
try name = map.from("name.first")
// Access the original JSON (maybe for use with a transformation)
try JSON = map.from("")
}
}
有关更多信息和其他示例,请参阅文档字符串和测试。
打开雷达
这些雷达影响了当前Mapper的实现
- rdar://23376350 带初始器的协议扩展在扩展中不工作
- rdar://23358609 带初始器的协议扩展与类配合不佳
- rdar://23226135 无法符合类似泛型函数签名的协议
- rdar://23147654 泛型函数无法通过其抛出能力进行区分
- rdar://23695200 多次使用
??
操作符是不可持续的。 - rdar://23697280 惰性集合元素可能会被多次评估。
- rdar://23718307 返回
Self
的非最终类与协议扩展不兼容
许可证
Mapper由Lyft维护,并根据Apache 2.0许可证发布。有关详情,请参阅LICENSE。