LoginSignup
40
24

More than 5 years have passed since last update.

CodableでCamelCase⇄SnakeCaseの変換を行う(keyDecodingStrategy/keyEncodingStrategy)

Last updated at Posted at 2018-02-20

はじめに

Xcode9.3からデフォルトのSwift versionが4.0から4.1へと上がります。
いくつかの改善点がありますが、Codable周りで役立ちそうな改善がありましたので、
メモがてら共有いたします。

以下の記載は2/20時点のβ版の情報にもとづき作成しています。
fix版リリース時には変更になる可能性がありますのでご注意下さい。

CamelCaseとSnakeCase

iOSでは一般的にプロパティの名称にCamelCaseを使用することが多いかと思います。
例えば下記のような構造体の定義です。

Struct定義
struct Person: Codable {
    let firstName: String
    let lastName: String
    let age: String
    let gender: String
}

ただ、一方でサーバの通信APIのレスポンスでは下記のようなSnakeCaseが用いられることがあります。

通信レスポンス例
{
  "first_name": "Tetsuya",
  "last_name": "Hayashi",
  "age": "30",
  "gender": "male"
}

このような通信レスポンスを上記で定義した Codableを適用したStructでパースしようとした場合、
このままではfirstNameとfirst_nameで名称が異なるためパースができません。
このような場合は、PersonをSnakeCaseで書くか、以下のようなCodingKeyを別途定義する必要がありました。プロパティの数が少ない場合はまだ良いですが、毎回CodingKeyを定義するのも冗長な気がします。

CondingKeySample
struct Person: Codable {
    let firstName: String
    let lastName: String
    let age: String
    let gender: String

    private enum CodingKeys: String, CodingKey {
        case firstName = "first_name"
        case lastName = "last_name"
        case age
        case gender
    }
}

Swift4.1からはこの問題を解決するプロパティがJsonDecoder/JsonEncoderに追加されました。

keyDecodingStrategy/keyEncodingStrategyについて

JsonDecoderにkeyDecodingStrategy、JsonEncoderにkeyEncodingStrategyプロパティが追加されています。これらのプロパティを設定することで、 CamelCase⇄SnakeCaseの変換を簡単に行うことができます。
例えば、先ほどのjsonを構造体のPersonにパースする場合は下記のようになります。
CodingKeysが必要なくなり、随分すっきりしました。

JsonDecoder

let personJson = """
{
  "first_name": "Tetsuya",
  "last_name": "Hayashi",
  "age": "30",
  "gender": "male"
}
""".data(using: .utf8)!

let jsonDecoder = JsonDecoder()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase // ここでsnakeCaseからの変換を指定

do {
    let person = try jsonDecoder.decode(Person.self, from: personJson)
    print(person)
} catch {
    print(error.localizedDescription)
}

逆にEncodingの際に、CamelCaseをSnakeCaseに変換することも可能です。

JsonEncoder
let person = Person(firstName: "Tetsuya", lastName: "Hayashi", age: "30", gender: "male")

let jsonEncoder = JSONEncoder()
jsonEncoder.keyEncodingStrategy = .convertToSnakeCase // ここでsnakeCaseへの変換を指定
do {
    let json = try jsonEncoder.encode(person)
    print(json)
} catch {
    print(error.localizedDescription)
}

所感

Codableが登場した際はとても便利になったと驚きましたが、さらに改善されていきますね。
コードを書くのがより楽しくなりそうです。

備考

本日、公開後にNDAに抵触するのではないかと考え、記事を削除いたしました。しかしながら、1:一般の方がアクセスできる公式ドキュメントに具体的な使用例も含み記載があること、2:Swiftはオープンソースであり、誰しもがアクセスできることから本記事記載の内容はNDAに抵触しないだろうと判断し、再度投稿を行なっています。
おそらく大丈夫だろうという考えでいますが、違反している可能性もありますので、その場合はご指摘いただけますと幸いです。確認の上、削除の検討をいたします。

参考資料

40
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
24