Object Serialization in Swift (iOS/macOS): Codable, JSON and PropertyList
Serialization is the process of converting data objects into a format suitable for storage or transmission (e.g., JSON, XML, Property List). In the Apple ecosystem (iOS, macOS, watchOS, tvOS), Swift provides a powerful and elegant mechanism for serialization and deserialization — the Codable protocol. In this article, we will thoroughly examine how to use Codable, JSONEncoder, PropertyListEncoder, and their counterparts for working with data.
What is Codable?
Codable is a composite protocol that combines Encodable (for encoding an object into an external format) and Decodable (for decoding from an external format into an object). If your Swift structure or class conforms to Codable, you automatically gain the ability to serialize and deserialize it.
Basic declaration:
struct User: Codable { let id: Int let name: String let email: String}All standard Swift types (String, Int, Double, Bool, Date, Data, URL, and even optional types and arrays/dictionaries) already conform to Codable.
Encoding to JSON
To encode an object into JSON, use JSONEncoder. Example:
let user = User(id: 1, name: "Ivan Petrov", email: "ivan@example.com")let encoder = JSONEncoder()encoder.outputFormatting = .prettyPrinted // for pretty output
do { let jsonData = try encoder.encode(user) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("Encoding error: \\(error)")}Result:
{ "id" : 1, "name" : "Ivan Petrov", "email" : "ivan@example.com"}Decoding from JSON
For the reverse transformation, use JSONDecoder:
let jsonString = """{ "id": 2, "name": "Maria Sidorova", "email": "maria@example.com"}"""let jsonData = Data(jsonString.utf8)let decoder = JSONDecoder()
do { let decodedUser = try decoder.decode(User.self, from: jsonData) print("Decoded user: \\(decodedUser.name)")} catch { print("Decoding error: \\(error)")}Working with Property List (plist)
For serialization into XML Property List format, use PropertyListEncoder and PropertyListDecoder. This is useful for storing data in configuration files or UserDefaults.
// Encoding to plistlet encoder = PropertyListEncoder()encoder.outputFormat = .xml
do { let plistData = try encoder.encode(user) // plistData can be saved to a file or UserDefaults} catch { print("Plist encoding error: \\(error)")}
// Decoding from plistlet decoder = PropertyListDecoder()do { let decodedUser = try decoder.decode(User.self, from: plistData) print(decodedUser)} catch { print("Plist decoding error: \\(error)")}Custom Keys (CodingKeys)
Sometimes property names in Swift do not match keys in JSON. For this, the CodingKeys enumeration is used:
struct Product: Codable { let productId: Int let productName: String let price: Double
enum CodingKeys: String, CodingKey { case productId = "product_id" case productName = "product_name" case price }}Now JSON with keys product_id and product_name will be correctly processed.
Handling Dates and Other Special Types
By default, JSONEncoder and JSONDecoder encode dates as TimeInterval
Also in library
Reactive Programming in Go (Golang): Libraries, Patterns, and Examples
Working with Excel in PHP: PhpSpreadsheet, PhpOffice Libraries and XLSX Generation
PHP-CS-Fixer Guide: Complete Tutorial with Examples for PHP
Database Migrations in C++: Overview of Tools and Libraries