【Swift】キャメルケース⇄スネークケースの変換がしたいとき

APIレスポンスがスネークケース、でもSwiftではキャメルケースを利用するので変換が必要になる場合がある。
さらにAPIリクエストにデータを載せて返す場合、キャメルからスネークに帰変える場合も出てくる。
その変換作業の備忘録。

enumで管理する場合

SwaggerのデータをOpenAPI generatorでモデルを自動生成する場合があり、パラメータがenum管理されていたりした。

enum Juice: String {
    case orangeJuice = "orange_juice"
    case grapeJuice = "grape_juice"
    case lemonJuice = "lemon_juice"
    case soda = "soda"
}

これをうちのプロジェクトでは別途モデルを作成して、API取得をした段階でレスポンスからモデルを生成する。
その際に入れ替えた方用のenum等も別途用意しているのだけれど、こっちはコード内で利用するのでキャメルに落とす。

// case と同じStringを用意したいならrawValueは省略できる
enum JuiceForModel: String {
    case orangeJuice
    case grapeJuice
    case lemonJuice
    case soda
}

これを相互変換したい。

やり方

変換はいろいろやり方はあるだろうけど、まず以下のやり方。

let value: Juice = .soda

let translatedValue = JuiceForModel(rawValue: value)

このやり方だと、変換元が変換先のと値と同じ場合のみ正常に変換される。
この場合 soda のみ。

なので今回はこういうやり方で変換した。

// キャメルケースのeunmに変換(コードで使う方)
extension JuiceForModel {
    init(from value: Juice) {
        switch value {
        case orangeJuice: self = .orangeJuice
        case grapeJuice: self = .grapeJuice
        case lemonJuice: self = .lemonJuice
        case soda: self = .soda
        }
    }
}

let value: Juice = .orangeJuice
let translatedValue = JuiceForKind(from: value)
print (translatedValue.rawValue) // orangeJuice
// スネークケースのenumに変換(APIリクエストのパラメーターとかで利用)
extension Juice {
    init(from value: JuiceForModel) {
        switch value {
        case orangeJuice: self = .orangeJuice
        case grapeJuice: self = .grapeJuice
        case lemonJuice: self = .lemonJuice
        case soda: self = .soda
        }
    }
}

let value: JuiceForKind = .orangeJuice
let translatedValue = Juice(from: value)
print (translatedValue.rawValue) // orange_Juice

こんな感じ。調べると変換メソッド系は出てくるけど、これならわざわざキャメル変換メソッドやらスネーク検索メソッドなどを用意しなくても良い。
enum使ってる前提になるけどね。