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.
WithPackage Manager
.package(name:"Mapper", url:"https://github.com/polarcop/mapper.git",.upToNextMajor(from:"1.0.0"))import Mapper
// Conform to the Mappable protocol
structUser:Mappable{letid:StringletphotoURL:URL?
// Implement this initializer
init(map:Mapper)throws{try id = map.from("id")
photoURL = map.optionalFrom("avatar_url")}}
// Create a user!
letJSON:[String:Any]=...letuser=User.from(JSON) // This is a 'User?'enumUserType:String{case Normal ="normal"case Admin ="admin"}structUser:Mappable{letid:Stringlettype:UserTypeinit(map:Mapper)throws{try id = map.from("id")try type = map.from("user_type")}}structUser:Mappable{letid:Stringletname:Stringinit(map:Mapper)throws{try id = map.from("id")try name = map.from("name")}}structGroup:Mappable{letid:Stringletusers:[User]init(map:Mapper)throws{try id = map.from("id")
users = map.optionalFrom("users")??[]}}extensionCLLocationCoordinate2D:Convertible{publicstaticfunc fromMap(_ value:Any)throws->CLLocationCoordinate2D{guardlet location = value as?[String:Any],let latitude =location["lat"]as?Double,let longitude =location["lng"]as?Doubleelse{throwMapperError.convertibleError(value: value, type:[String:Double].self)}returnCLLocationCoordinate2D(latitude: latitude, longitude: longitude)}}structPlace:Mappable{letname:Stringletlocation:CLLocationCoordinate2Dinit(map:Mapper)throws{try name = map.from("name")try location = map.from("location")}}letJSON:[String:Any]=["name":"Polar HQ","location":["lat":51.504949,"lng":-0.019501,],]letplace=Place.from(JSON)privatefunc extractFirstName(object:Any?)throws->String{guardlet fullName = object as?Stringelse{throwMapperError.convertibleError(value: object, type:String.self)}letparts= fullName.characters.split{ $0 ==""}.map(String.init)iflet firstName = parts.first {return firstName
}throwMapperError.customError(field:nil, message:"Couldn't split the string!")}structUser:Mappable{letfirstName:Stringinit(map:Mapper)throws{try firstName = map.from("name", transformation: extractFirstName)}}structUser:Mappable{letname:StringletJSON:AnyObjectinit(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