Logo for tanaschita.com

How to change JSON keys by using Swift's CodingKey protocol

Learn how to map JSON data to a different structure in Swift.

27 Mar 2023 · 3 min read

Swift's Codable protocol makes it easy to convert JSON data to native Swift types and the other way around. In the article on how to use the CodingKey protocol, we explored how to use custom names for Swift properties when decoding JSON data.

In some cases though, we might need an even more customized solution, for example to map the JSON data to a different structure.

Let's look at how to do that.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 18
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Let's say we get the following JSON data:

{
"username" : "tanaschita",
"validated": true,
"address": {
"postalCode": "04275",
"city": "Leipzig",
...
}
}

Our application is only interested in the user's city property, that's why we'd like to add it directly to our User struct without defining an extra Address type as follows:

struct User: Codable {
let username: String
let isValidated: Bool
let city: String
}

To be able to map the data the way we want, we can provide a custom implementation of Encodable and Decodable to define our own encoding and decoding logic:

struct User: Codable {
let username: String
let isValidated: Bool
let city: String
enum CodingKeys: String, CodingKey {
case username
case isValidated = "validated"
case address
}
enum AddressCodingKeys: String, CodingKey {
case city
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
username = try values.decode(String.self, forKey: .username)
isValidated = try values.decode(Bool.self, forKey: .isValidated)
let address = try values.nestedContainer(keyedBy: AddressCodingKeys.self, forKey: .address)
city = try address.decode(String.self, forKey: .city)
}
}

In the same way, we can add our own encoding logic:

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(username, forKey: .username)
try container.encode(isValidated, forKey: .isValidated)
var address = container.nestedContainer(keyedBy: AddressCodingKeys.self, forKey: .address)
try address.encode(city, forKey: .city)
}

This possibility gives us a way to be fully independent of the JSON structure so we can create an entirely customized representation of that data in our iOS apps.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 18
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

json

networking

swift

ios

How to use custom names for Swift properties when decoding JSON data

Learn to use Swift's CodingKey protocol.

20 Feb 2023 · 2 min read

Latest articles and tips

© 2024 tanaschita.com

Privacy policy

Impressum