Model data with structs
Use small types instead of loosely typed dictionaries.
Describe the shape
A struct groups related properties into a type. Instances have value semantics: assigning or passing a value behaves as a copy of the value. A class has reference semantics, where multiple references can point to the same instance.
Let protocols describe capabilities
Decodable represents the ability to read a value from a decoder. The compiler can synthesize it for many structs. Codable combines Decodable and Encodable when you need both directions.
Keep invalid states visible
Required properties should stay required when missing data is an error. Use optional properties only when absence is allowed by your model. Decode with do/catch and inspect errors rather than inventing an empty result.
Try it yourself
import Foundation
struct Developer: Decodable {
let name: String
let languages: [String]
}
let json = #"{"name":"Sam","languages":["Swift","Rust"]}"#
do {
let person = try JSONDecoder().decode(Developer.self, from: Data(json.utf8))
print(person.name)
print(person.languages.joined(separator: ", "))
} catch { print("Decoding failed: \(error)") }Use CodingKeys for mismatched names. Make fields optional only when missing or null is valid.