LoginSignup
28
14

More than 5 years have passed since last update.

CodingKeyで、case名のcamelCase ⇄ stringValueのsnake_case を自動で変換する

Last updated at Posted at 2017-06-20

CodingKeyのマッピングを動的に切り替える - Qiita を書いてたら、なんかできそうな気がしたので類似アプローチでもうひとネタ。
やってみたらできた。

extension String {
    var snakecased: String {
        return self.replacingOccurrences(
            of: "([A-Z])",
            with: "_$1",
            options: .regularExpression
            ).lowercased()
    }
    var camelcased: String {
        return self
            .components(separatedBy: "_")
            .enumerated()
            .map { 0 == $0.offset ? $0.element : $0.element.capitalized }
            .joined()
    }
}

struct S: Codable {
    let hogeFuga: Int

    enum CodingKeys: String, CodingKey {
        case hogeFuga

        init?(stringValue: String) {
            self.init(rawValue: stringValue.camelcased)
        }
        var stringValue: String {
            return rawValue.snakecased
        }
    }
}

import Foundation

let data = """
{
    "hoge_fuga": 10,
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let s0 = try! decoder.decode(S.self, from: data)
print(s0)

結果:

S(hogeFuga: 10)

思ったこと

String enum だったらrawValueだけでなんとかしなきゃいけないと思い込んでたけど、そもそもインタフェース的には init?(stringValue:) を噛ませてるから、そこの処理を自前で書いてしまえば結構自由にフックできるんですねー。

ちなみに、CodingKeyがコンパイラに自動生成されるときのコードはこんな感じらしいです。

  // enum SomeEnum {
  //   case A, B, C
  //   @derived init?(stringValue: String) {
  //     switch stringValue {
  //     case "A":
  //       self = .A
  //     case "B":
  //       self = .B
  //     case "C":
  //       self = .C
  //     default:
  //       return nil
  //     }
  //   }
  // }

  // enum SomeEnum {
  //   case A, B, C
  //   @derived var stringValue: String {
  //     switch self {
  //       case A:
  //         return "A"
  //       case B:
  //         return "B"
  //       case C:
  //         return "C"
  //     }
  //   }
  // }
28
14
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
28
14