Upgrade to Pro — share decks privately, control downloads, hide ads and more …

APIクライアントをCodableで置き換えた話

 APIクライアントをCodableで置き換えた話

potatotips #50

Keisuke Kobayashi

April 19, 2018
Tweet

More Decks by Keisuke Kobayashi

Other Decks in Programming

Transcript

  1. About Me Keisuke Kobayashi Twitter: @kobakei122 GitHub, Qiita: @Kobakei Kyash,

    Inc Android Engineer -> iOS Engineer -> Engineering Manager
  2. 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 { ... }
  3. Nested Object そのまま使える struct Author: Decodable { let name: String

    } struct Book: Decodable { let author: Author // 別のDecodable な構造体 }
  4. JSON のキーとstruct のキーが 違う CodingKey を作る struct Hoge: Decodable {

    let isDefault: Bool private enum CodingKeys: String, CodingKey { case isDefault = "default" } }
  5. 日付の文字列を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)
  6. JSON とstruct の構造が違う 同じキーでも型が違うJSON (辛い) [ { "type": "user", "target":

    { "firstName": "Keisuke", "lastName": "Kobayashi" } }, { "type": "store", "target": { "name": "Amazon" } } ]
  7. 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" に対応 } ...
  8. 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) } } }
  9. まとめ Codable いいぞ Alamo re 使ってるならCodableAlamo re いいぞ つらいJSON でもinit

    で自分でデコードすればなん とかなるけどつらいぞ