Mobile Development 9 min read

Using Swift 4.1 JSONEncoder/JSONDecoder KeyEncodingStrategy to Bridge Snake_case and CamelCase and Create Custom Key Strategies

This article explains how Swift 4.0 introduced Codable, how Swift 4.1 added keyEncodingStrategy and keyDecodingStrategy to automatically convert between snake_case and camelCase, and how to implement custom key transformations such as PascalCase using the .custom strategy.

Liulishuo Tech Team
Liulishuo Tech Team
Liulishuo Tech Team
Using Swift 4.1 JSONEncoder/JSONDecoder KeyEncodingStrategy to Bridge Snake_case and CamelCase and Create Custom Key Strategies

Swift 4.0 added the Codable protocol, which combines Encodable and Decodable , allowing the compiler to synthesize init(from: Decoder) and encode(to: Encoder) . Swift 4.1 introduced two new properties on JSONEncoder and JSONDecoder : keyEncodingStrategy and keyDecodingStrategy .

1. Bridging Snake_case and CamelCase

When a JSON payload uses snake_case keys but a Swift struct uses camelCase property names, decoding and encoding fail unless a custom CodingKeys enum is provided.

let jsonStr = """
{
  "age": 18,
  "first_name": "Leon"
}
"""

struct Person: Codable {
  var age: Int
  var firstName: String
}

In Swift 4.0 you would define:

enum CodingKeys: String, CodingKey {
  case age
  case firstName = "first_name"
}

Swift 4.1 simplifies this with built‑in strategies:

// Encoding
let leon = Person(age: 18, firstName: "Leon")
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let resultData = try? encoder.encode(leon)

// Decoding
let data = jsonStr.data(using: .utf8)!
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let person = try? decoder.decode(Person.self, from: data)

2. Custom Key Strategies

For other naming conventions, such as PascalCase, you can use the .custom case of the strategy, which receives a closure ([CodingKey]) -> CodingKey . The closure gets the full path of coding keys, typically using the last element.

struct SimpleCodingKey: CodingKey {
  var stringValue: String
  var intValue: Int?
  init(stringValue: String) { self.stringValue = stringValue }
  init(intValue: Int) {
    self.stringValue = "\(intValue)"
    self.intValue = intValue
  }
}

extension JSONEncoder.KeyEncodingStrategy {
  static var convertToPascalCase: JSONEncoder.KeyEncodingStrategy {
    return .custom { codingKeys in
      let str = codingKeys.last!.stringValue
      guard let firstChar = str.first else { return SimpleCodingKey(stringValue: str) }
      let s = str.prefix(1).capitalized + str.dropFirst()
      return SimpleCodingKey(stringValue: s)
    }
  }
}

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToPascalCase
let resultData = try? encoder.encode(leon)

Note that SimpleCodingKey 's initializer is non‑failable, yet it satisfies the protocol’s failable initializer requirement. The extension adds a static variable that can be used like an enum case.

Decoding can be handled similarly by providing a counterpart that lower‑cases the first character.

3. Design Highlights

Interface‑based OOP: The CodingKey protocol abstracts key handling, enabling the addition of custom strategies without changing the encoder/decoder core. The overall design of Encoder , Decoder , and Codable is based on protocols, making it format‑agnostic.

Associated‑value enums for configuration: The KeyEncodingStrategy and KeyDecodingStrategy enums use associated values (e.g., .custom(([CodingKey]) -> CodingKey) ) to allow elegant, runtime‑configurable behavior, similar to other strategies like dateEncodingStrategy .

Generics and metatype programming: Decoding is performed with try decoder.decode(Person.self, from: data) , where Person.self is a metatype. The generic signature func decode (_ type: T.Type, from data: Data) throws -> T where T: Decodable showcases Swift’s powerful generic and metatype capabilities.

Conclusion

Codable, introduced in Swift 4.0 and enhanced in Swift 4.1, provides a first‑class, compiler‑synthesized serialization solution for Swift. Its design offers interface‑driven extensibility, elegant strategy configuration via associated‑value enums, and leverages generics and metatypes, making it a top choice for Swift developers building mobile applications.

mobile developmentJSONSwiftCodableKeyEncodingStrategy
Liulishuo Tech Team
Written by

Liulishuo Tech Team

Help everyone become a global citizen!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.