モノトーンの伝説日記

Apex Legendsが大好き。

<mini> Swift (4.1 以降) で `.convertFromSnakeCase` を使いながらも property name を変更する

 お久しぶりです。最近プログラミング熱が熱いモノトーンです。

 今日は Swift 4.1 以降で追加されている .convertFromSnakeCase 利用時における挙動について解説します。

import Foundation

extension Decodable {
    static func decode(json data: Data) throws -> Self {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        return try decoder.decode(Self.self, from: data)
    }
}

のように,お手軽 JSON デコーダー環境を仕込むのは当たり前だと思います。

 RxSwift を使いながら

guard let model = try? Model.decode(json: data) else {
    observer(.error(ClientError.invalidModel))
    return
}
                    
observer(.success(model))

のようにするのが理想かなーっと。ちなみに Model.decode(xml: Data) みたいな API 生やせば色々なフォーマットにお手軽対応できるので,引数の json: は必ず要求する設計にしています。

 それは置いて置くとして,.convertFromSnakeCase を使っているときの問題。プロパティー名を変更したいと思ったんだけど毎回エラーが発生するんですよね。どうやら仕組み上

  1. .convertFromSnakeCase にしたがって変換され,
  2. CodingKeys に camel case の名前を用いて割り当てられる

というプロセスをたどっているらしいです。ですので,

⭕️

struct SampleEntity: Codable {
    let id: String
    let pageUrl: String
    let subPageUrl: String
    
    private enum CodingKeys: String, CodingKey {
        case id
        case pageUrl
        case subPageUrl = "pageUrl2"
    }
}

って感じになると思います。CodingKeys を使っているときは,camel case に変換されないと思って,

struct SampleEntity: Codable {
    let id: String
    let pageUrl: String
    let subPageUrl: String
    
    private enum CodingKeys: String, CodingKey {
        case id
        case pageUrl = "page_url"
        case subPageUrl = "page_url2"
    }
}

みたいな書き方をすると,一致する key がないとしてデコードに失敗する,っぽい。挙動をちゃんと確かめたわけじゃないので,アレですが……w 多分あってるかと。