Mapper is a tiny and simple library which allows you to convert Zewo's StructuredData
to strongly typed objects. Deeply inspired by Lyft's Mapper.
import Mapper
struct User: Mappable {
let id: Int
let username: String
let city: String?
// Mappable requirement
init(mapper: Mapper) throws {
id = try mapper.map(from: "id")
username = try mapper.map(from: "username")
city = mapper.map(optionalFrom: "city")
}
}
let content: StructuredData = [
"id": 1654,
"username": "fireringer",
"city": "Houston"
]
let user = User.makeWith(structuredData: content) // User?
Be careful! If you use map(from:)
instead of map(arrayFrom:)
, mapping will fail.
struct Album: Mappable {
let songs: [String]
init(mapper: Mapper) throws {
songs = try mapper.map(arrayFrom: "songs")
}
}
struct Album: Mappable {
let songs: [String]?
init(mapper: Mapper) throws {
songs = try mapper.map(optionalArrayFrom: "songs")
}
}
You can use Mapper for mapping enums with raw values. Right now you can use only String
, Int
and Double
as raw value.
enum GuitarType: String {
case acoustic
case electric
}
struct Guitar: Mappable {
let vendor: String
let type: GuitarType
init(mapper: Mapper) throws {
vendor = try mapper.map(from: "vendor")
type = try mapper.map(from: "type")
}
}
struct League: Mappable {
let name: String
init(mapper: Mapper) throws {
name = try mapper.map(from: "name")
}
}
struct Club: Mappable {
let name: String
let league: League
init(mapper: Mapper) throws {
name = try mapper.map(from: "name")
league = try mapper.map(from: "league")
}
}
Mappable
is great for complex entities, but for the simplest one you can use StructuredDataInitializable
protocol. StructuredDataInitializable
objects can be initializaed from StructuredData
itself, not from its Mapper
. For example, Mapper uses StructuredDataInitializable
to allow seamless Int
conversion:
extension Int: StructuredDataInitializable {
public init(structuredData value: StructuredData) throws {
switch value {
case .numberValue(let number):
self.init(number)
default:
throw InitializableError.cantBindToNeededType
}
}
}
Now you can map Int
using from(_:)
just like anything else:
struct Generation: Mappable {
let number: Int
init(mapper: Mapper) throws {
number = try mapper.map(from: "number")
}
}
Conversion of Int
is available in Mapper out of the box, and you can extend any other type to conform to StructuredDataInitializable
yourself, for example, NSDate
:
import Foundation
import Mapper
extension StructuredDataInitializable where Self: NSDate {
public init(structuredData value: StructuredData) throws {
switch value {
case .numberValue(let number):
self.init(timeIntervalSince1970: number)
default:
throw InitializableError.cantBindToNeededType
}
}
}
extension NSDate: StructuredDataInitializable { }
- Add
Mapper
to yourPackage.swift
import PackageDescription
let package = Package(
dependencies: [
.Package(url: "https://github.com/Zewo/Mapper.git", majorVersion: 0, minor: 5),
]
)
If you need any help you can join our Slack and go to the #help channel. Or you can create a Github issue in our main repository. When stating your issue be sure to add enough details, specify what module is causing the problem and reproduction steps.
The entire Zewo code base is licensed under MIT. By contributing to Zewo you are contributing to an open and engaged community of brilliant Swift programmers. Join us on Slack to get to know us!
This project is released under the MIT license. See LICENSE for details.