What is Codable in Swift? How to use Codable for encoding and decoding? What are the differences between CustomStringConvertible and CustomDebugStringConvertible?
Codable in Swift is a type alias that combines the Encodable and Decodable protocols, used for converting between data types and external representations (such as JSON, Property List).
Basic Usage of Codable:
swiftstruct User: Codable { let id: Int let name: String let email: String } // Encoding let user = User(id: 1, name: "John Doe", email: "john@example.com") let encoder = JSONEncoder() if let jsonData = try? encoder.encode(user) { print(String(data: jsonData, encoding: .utf8)!) } // Decoding let decoder = JSONDecoder() if let decodedUser = try? decoder.decode(User.self, from: jsonData) { print(decodedUser.name) }
Custom Coding Keys:
swiftstruct User: Codable { let id: Int let name: String let email: String enum CodingKeys: String, CodingKey { case id case name = "full_name" case email = "email_address" } }
Custom Encoding and Decoding:
swiftstruct DateWrapper: Codable { let date: Date enum CodingKeys: String, CodingKey { case timestamp } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let timestamp = try container.decode(Double.self, forKey: .timestamp) self.date = Date(timeIntervalSince1970: timestamp) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(date.timeIntervalSince1970, forKey: .timestamp) } }
Notes on Codable:
- All properties must be Codable types
- Optional types automatically support Codable
- Arrays and dictionaries automatically support Codable if elements are Codable types
- Can use CodingKeys to customize key names
CustomStringConvertible:
- Used to provide custom string representation
- Implement
descriptionproperty - Used in
print()andString(describing:) - Example:
swift
struct Point: CustomStringConvertible { let x: Int let y: Int var description: String { return "(\(x), \(y))" } } let point = Point(x: 3, y: 4) print(point) // (3, 4)
CustomDebugStringConvertible:
- Used to provide string representation for debugging
- Implement
debugDescriptionproperty - Used for descriptions in debugger
- Higher priority than CustomStringConvertible
- Example:
swift
struct User: CustomDebugStringConvertible { let id: Int let name: String let password: String var debugDescription: String { return "User(id: \(id), name: \(name))" } } let user = User(id: 1, name: "John", password: "secret") debugPrint(user) // User(id: 1, name: John)
Differences Between CustomStringConvertible and CustomDebugStringConvertible:
-
Different Purposes:
- CustomStringConvertible: for regular string representation
- CustomDebugStringConvertible: for debug string representation
-
Different Implementation Methods:
- CustomStringConvertible: implement
descriptionproperty - CustomDebugStringConvertible: implement
debugDescriptionproperty
- CustomStringConvertible: implement
-
Different Call Scenarios:
- CustomStringConvertible:
print(),String(describing:) - CustomDebugStringConvertible:
debugPrint(), debugger
- CustomStringConvertible:
-
Different Priorities:
- When both implemented, CustomDebugStringConvertible has higher priority
- Use debugDescription during debugging
- Use description for regular use
Best Practices:
- Implement Codable for data models
- Use CodingKeys to handle key name mismatches
- Implement CustomStringConvertible for custom types
- Implement CustomDebugStringConvertible for debugging
- Hide sensitive information in debugDescription