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<T>(_ 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.