Skip to content

Instantly share code, notes, and snippets.

@mfaani
Last active December 19, 2022 15:42
Show Gist options
  • Save mfaani/65657aca6ca50a8dbde6f5547491e9ab to your computer and use it in GitHub Desktop.
Save mfaani/65657aca6ca50a8dbde6f5547491e9ab to your computer and use it in GitHub Desktop.
A quick example of codeable based off of a Hackingwithswift tutorial
// https://www.hackingwithswift.com/articles/119/codable-cheat-sheet
import Foundation
struct Packet: Decodable {
var value: Int
var array: [Packet]?
}
enum Lett {
indirect case a(m: M)
case b
}
enum M {
case b(m: Lett)
}
let json = """
[
{
"name": {
"first_name": "Taylor",
"last_name": "Swift"
},
"age": 26
}
]
"""
struct User: Codable {
var firstName: String
var lastName: String
var age: Int
enum CodingKeys: String, CodingKey {
case name, age
}
enum NameCodingKeys: String, CodingKey {
case firstName, lastName
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
age = try container.decode(Int.self, forKey: .age)
let name = try container.nestedContainer(keyedBy: NameCodingKeys.self, forKey: .name)
firstName = try name.decode(String.self, forKey: .firstName)
lastName = try name.decode(String.self, forKey: .lastName)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(age, forKey: .age)
var name = container.nestedContainer(keyedBy: NameCodingKeys.self, forKey: .name)
try name.encode(firstName, forKey: .firstName)
try name.encode(lastName, forKey: .lastName)
}
}
let decoder = JSONDecoder()
// 1.
decoder.keyDecodingStrategy = .convertFromSnakeCase
// 2.
// let user1 = try! decoder.decode(User.self, from: json.data(using: .utf8)!)
let user2 = try! decoder.decode([User].self, from: json.data(using: .utf8)!)
// print(user1)
print(user2)
/* EDUCATIONAL NOTES:
1. Things break if I remove `convertFromSnakeCase`.
2. Things break if I decode it to `User.self` instead of `[User].self`.
Attempting to break it, helps you better understand how things work.
The way I think of `let container = try decoder.container(keyedBy: CodingKeys.self)` is:
container is just a _way_ to see what was passed to the decoder. In this context it means it's a window into the passed json.
Your container has different items you can open. Each item is opened with a specific coding key.
Your json has two fields (name, age). Think of it as two locks (key). Each lock can be opened with a unique key (or matching key).
Then you have a new container. You can either open more keys (firstName, lastName) in this container or just map it to a field of the type your decoding
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment