ObjectMapperでJSONマッピング
@ikesyo
関西モバイルアプリ研究会!2015&04&17!Fri!#関モバ
@ikesyo
いけしょー/池田翔
京都でフリーランスのiOSエンジニア
(時々Android)しています
現在はフリュー㈱のモバイル開発の
チームにジョイン中。
Swi$もReac)veCocoaも使ってます。
Reac%veCocoaのコミッター(Contributor)やってます
ところで
Swi$でJSON(<=>(オブジェクトの
マッピングってどうしてますか?
Objec&ve(C時代の定番*=>*Mantle
Mantle'in'Swi+
• Objec've)CのランタイムAPI
• dynamic var
• 型安全ではない
• struct.や.enum.が使えない
Swi$ネイティブなJSONマッパーを
ObjectMapper
ObjectMapper
• h#ps://github.com/Hearst5DD/ObjectMapper
• JSONのシリアライズ・デシリアライズ両方に対応
• Argo>(h#ps://github.com/thoughtbot/Argo)>はデシリアライズ
だけの方向性
ObjectMapper
• プロトコルベースのAPI
• 継承の必要なし
• class%も%struct%も使える。
• rawValue%を持つ%enum%のプロパティも持てる
Mappable
public protocol Mappable {
init?(_ map: Map)
mutating func mapping(map: Map)
}
mutating!によって!struct!でも使えます。
サンプルコード
class User: Mappable {
var username: String?
var age: Int?
var array: [AnyObject]?
var group: Gruop? // 別の`Mappable`な型
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
username <- map["username"]
age <- map["age"]
array <- map["array"]
group <- map["group"]
}
}
class Group: Mappable { ... }
サンプルコード
let JSON: [String: AnyObject] = [
"username": "ikesyo",
"age": 28,
"array": [ 1, 2.0, "hoge", true ],
"group": [ ... ]
]
let mapper = Mapper<User>()
let user: User? = mapper.map(JSON)
let JSONFromUser: [String: AnyObject] = mapper.toJSON(user!)
サンプルコード
let mapper = Mapper<User>()
let usersJSON: [[String: AnyObject]] = ... // ルート要素が配列のJSON
let users: [User] = mapper.mapArray(usersJSON)
let usersJSONDict: [String: [String: AnyObject]] = ...
let usersDict: [String: User] = mapper.mapDictionary(usersJSONDict)
Transform
class WithTransform: Mappable {
var URL: NSURL?
var date: NSDate?
var intFromString: Int?
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
URL <- (map["url"], URLTransform())
date <- (map["date"], ISO8601DateTransform())
intFromString <- (map["int_from_string"], TransformOf<Int, String>(
fromJSON: { (JSONValue: String?) -> Int? in JSONValue?.toInt() },
toJSON: { (value: Int?) -> String? in value.map { String($0) } }))
}
}
こんなやつも使えます。
struct Immutable: Mappable {
let prop1: String
let prop2: Bool
let prop3: Int
init?(_ map: Map) {
prop1 = map["prop1"].valueOrFail() // nilの場合は`T`型のダミー値をセット
prop2 = map["prop2"].valueOrFail()
prop3 = map["prop3"].valueOr(Int.min) // デフォルト値
// ダミー値がセットされていれば初期化失敗
if !map.isValid {
return nil
}
}
}
こんなやつも使えます。
struct Immutable: Mappable {
...
mutating func mapping(map: Map) {
switch map.mappingType {
case .FromJSON:
if let x = Immutable(map) {
self = x
}
case .ToJSON:
var prop1 = self.prop1
var prop2 = self.prop2
var prop3 = self.prop3
prop1 <- map["prop1"]
prop2 <- map["prop2"]
prop3 <- map["prop3"]
}
}
}
Collaboratorではないですが、色々対応しています。
ありがとうございました!

ObjectMapperでJSONマッピング