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("")
  }
}

查看文档字符串和测试以获取更多信息和示例。

公开的 Radars

以下 radars 影响了 Mapper 的当前实现

许可

Mapper 由 Lyft 维护,并根据 Apache 2.0 许可证发布。 有关详细信息,请参见 LICENSE