Skip to content
This repository was archived by the owner on May 17, 2024. It is now read-only.

Repository files navigation

Mapper

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.

Installation

use_frameworks!pod"ModelMapper"
github "lyft/mapper"

Usage

Simple example:

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:NSDictionary=...letuser=User.from(JSON) // This is a 'User?'

Using with enums:

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

Nested Mappable objects:

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")??[]}}

Use Convertible to transparently convert other types from JSON:

extensionCLLocationCoordinate2D:Convertible{publicstaticfunc fromMap(_ value:Any)throws->CLLocationCoordinate2D{guardlet location = value as?NSDictionary,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:NSDictionary=["name":"Lyft HQ","location":["lat":37.7603392,"lng":-122.41267249999999,],]letplace=Place.from(JSON)

Custom Transformations

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

Parse nested or entire objects

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

See the docstrings and tests for more information and examples.

Open Radars

These radars have affected the current implementation of Mapper

  • rdar://23376350 Protocol extensions with initializers do not work in extensions
  • rdar://23358609 Protocol extensions with initializers do not play well with classes
  • rdar://23226135 Can't conform to protocols with similar generic function signatures
  • rdar://23147654 Generic functions are not differentiated by their ability to throw
  • rdar://23695200 Using the ?? operator many times is unsustainable.
  • rdar://23697280 Lazy collection elements can be evaluated multiple times.
  • rdar://23718307 Non final class with protocol extensions returning Self don't work

License

Mapper is maintained by Lyft and released under the Apache 2.0 license. See LICENSE for details

About

A JSON deserialization library for Swift

Topics

Resources

Contributing

Stars

1.2k stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages