Heavily based on the Lyft implementation, this library has been refactored for Swift 5.0 and enables Swift Package.
Mapper is a simple Swift library to convert JSON to strongly typed objects. One advantage to Mapper over some other libraries is you can have immutable properties.
With Package Manager
.package(name: "Mapper", url: "https://github.com/polarcop/mapper.git", .upToNextMajor(from: "1.0.0"))
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: [String: Any] = ... 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") } }
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") ?? [] } }
extension CLLocationCoordinate2D: Convertible { public static func fromMap(_ value: Any) throws -> CLLocationCoordinate2D { guard let location = value as? [String: Any], 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: [String: Any] = [ "name": "Polar HQ", "location": [ "lat": 51.504949, "lng": -0.019501, ], ] 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 is maintained by Polar and released under the Apache 2.0 license. See LICENSE for details