objectmapperでjsonマッピング
TRANSCRIPT
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ではないですが、色々対応しています。
ありがとうございました!