Slide 1

Slide 1 text

API クライアントをCodable で 置き換えた話 Keisuke Kobayashi / @kobakei potatotips #50

Slide 2

Slide 2 text

About Me Keisuke Kobayashi Twitter: @kobakei122 GitHub, Qiita: @Kobakei Kyash, Inc Android Engineer -> iOS Engineer -> Engineering Manager

Slide 3

Slide 3 text

会社のブログ Kyash iOS アプリの大規模リファクタリングの話 http://blog.kyash.co/entry/2018/03/20/150238 ちょっとだけバズった

Slide 4

Slide 4 text

Codable Swift 4 ~ JSON のシリアライズとデシリアライズの仕組み

Slide 5

Slide 5 text

Sample struct Hoge: Codable { let foo: String let bar: String? } let data: Data = ... let decoder: JSONDecoder = JSONDecoder() do { let hoge: Hoge = try decoder.decode(Hoge.self, from: data) print(newJson) //Success!!! } catch { ... }

Slide 6

Slide 6 text

実際のAPI をCodable に置き換 えた

Slide 7

Slide 7 text

CodableAlamo re https://github.com/Otbivnoe/CodableAlamo re responseDecodableObject が追加される

Slide 8

Slide 8 text

CodableAlamo re response.result.value で変換後のオブジェクト取得 Alamofire.request(url) .responseDecodableObject { (res: DataResponse) in let hoge = res.result.value print(hoge) }

Slide 9

Slide 9 text

enum enum Brand: String, Decodable { case visa = "visa" case mastercard = "mastercard" }

Slide 10

Slide 10 text

Nested Object そのまま使える struct Author: Decodable { let name: String } struct Book: Decodable { let author: Author // 別のDecodable な構造体 }

Slide 11

Slide 11 text

JSON のキーとstruct のキーが 違う 例) default はSwift の予約語だからisDefault にした い { "default": true }

Slide 12

Slide 12 text

JSON のキーとstruct のキーが 違う CodingKey を作る struct Hoge: Decodable { let isDefault: Bool private enum CodingKeys: String, CodingKey { case isDefault = "default" } }

Slide 13

Slide 13 text

日付の文字列をDate に変換す る dateDecodingStrategy にフォーマッタをセット let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSxxx" dateFormatter.locale = Locale(identifier: "en_US_POSIX") // ↑ これがないと12 時間表記モードでパースできない let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(dateFormatter) let newJson: Hoge = try decoder.decode(Hoge.self, from: data)

Slide 14

Slide 14 text

JSON とstruct の構造が違う 同じキーでも型が違うJSON (辛い) [ { "type": "user", "target": { "firstName": "Keisuke", "lastName": "Kobayashi" } }, { "type": "store", "target": { "name": "Amazon" } } ]

Slide 15

Slide 15 text

JSON とstruct の構造が違う それぞれのstruct を別のフィールドにする public struct Transaction: Decodable { let type: String let user: User? let store: Store? private enum CodingKeys: String, CodingKey { case type case target // JSON のキー"target" に対応 } ...

Slide 16

Slide 16 text

JSON とstruct の構造が違う init を自分で実装する(めんどくさい) decode のキーはいずれもtarget を使う ... public init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys. type = try values.decode(String.self, forKey: .type) if type == "user" { user = try values.decode(User.self, forKey: .target) } else if type == "store" { store = try values.decode(Store.self, forKey: .target) } } }

Slide 17

Slide 17 text

まとめ Codable いいぞ Alamo re 使ってるならCodableAlamo re いいぞ つらいJSON でもinit で自分でデコードすればなん とかなるけどつらいぞ

Slide 18

Slide 18 text

Try! Codable