14
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

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

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"
  //     }
  //   }
  // }
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
14
Help us understand the problem. What are the problem?