Swiftで利用できるLooseCodableというライブラリを作った
LooseCodableというライブラリを作った。
CarthageとSwiftPackageManagerからインストールして利用することができる。
このライブラリを作ろうと思った動機だが、サーバーサイドのAPIレスポンスが安定していないというのが理由だ。
主にIntegerとString、IntegerとBooleanの型が様々な形式で返ってくるのだが、SwiftのCodable
*1はこれらの型を曖昧に変換することを許さず例外を投げてくる。
例えば、Booleanで扱いたいケースで0
か1
で返ってくるケースとtrue
かfalse
で返ってくるケースが混在しているだとか、10
で返ってくるか"10"
で返ってくるかが混在しているかなど…
Codable
登場以前は自前で書いたマッパーがこのあたりの差異をいい感じに吸収してくれていたのだが、Codable
へ移行したと同時にこのような問題が顕在化してしまった。
Codable
を利用すること自体は間違いのない選択だと考えているが、この気まぐれなAPIとは相性が悪い。
そこで、この気まぐれAPIを快く受け入れるべくLooseCodableを作ったというわけだ。
さて、このライブラリだが期待する型をLooseCodable
という型で包んであげることでいい感じに差異を吸収してくれるものだ。
struct Hito: Codable { // このように定義しておくと let age: LooseCodable<Int> } // こんなデータが let json = """ { "age": "10" } """ // デコードできちゃいます! let hito = try! JSONDecoder().decode(Hito.self, from: json.data(using: .utf8)!) print(hito.age.value) // 10
上記のコードだとLooseCodable
という型が表面に出てしまい、結果の値を得るためにvalue
というプロパティを呼ぶのは、呼び出し側に多くの変更の負担が寄る可能性がありいただけない。
そもそもLooseCodable
はCodableオブジェクトの外に見えている必要は無い。
このため定義するとき、LooseCodable
を指定する型はプライベートにしておき、公開するプロパティをComputedにしたほうが良いだろう。
struct Hito { // LooseCodableなプロパティは非公開にし、 private let _age: LooseCodable<Int> // 利用される値をComputedな公開プロパティにする var age: Int { return self._age.value } // JSONとプロパティのキーマッピングを忘れずに enum CodingKeys: String, CodingKey { case _age = "age" } }
今回、初めてSwiftPackageManagerを利用してライブラリを公開してみたが、何もしなくてもCarthageでのインストールにも対応できていて中々に便利な代物だなと思えた。
ファイル構造を強制するなどとっつき憎い点もあったが、今後のSwiftにおけるライブラリ開発はSwiftPackageManagerで作成することを念頭に置いておきたいところだ。