Этот вопрос проверяет понимание механизмов преобразования объектов Swift в формат для хранения или передачи и обратно, что необходимо для работы с сетью, базой данных или файловой системой.
В Swift стандартный способ сериализации (преобразования объекта в данные, например, в JSON) и десериализации (восстановления объекта из данных) основан на протоколе Codable. Codable — это псевдоним типа, объединяющий протоколы Encodable (для кодирования) и Decodable (для декодирования). Это позволяет Swift автоматически генерировать код для преобразования между вашими типами и внешними представлениями, такими как JSON, Property List (plist) или другими форматами.
Чтобы сериализовать и десериализовать вашу модель, просто объявите её соответствующей протоколу Codable. Если все свойства типа уже соответствуют Codable (как большинство стандартных типов Swift), компилятор автоматически сгенерирует необходимые методы.
struct User: Codable {
var id: Int
var name: String
var email: String
}
// Сериализация (объект -> JSON Data)
let user = User(id: 1, name: "Alice", email: "alice@example.com")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // Для читаемого JSON
if let jsonData = try? encoder.encode(user) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
// Вывод: {"id":1,"name":"Alice","email":"alice@example.com"}
}
}
// Десериализация (JSON Data -> объект)
let decoder = JSONDecoder()
if let decodedUser = try? decoder.decode(User.self, from: jsonData) {
print(decodedUser.name) // Alice
}Часто имена ключей в JSON не совпадают с именами свойств в Swift (например, snake_case в JSON и camelCase в Swift). Для этого используется перечисление CodingKeys, которое определяет маппинг.
struct Product: Codable {
var productId: Int
var productName: String
var inStock: Bool
enum CodingKeys: String, CodingKey {
case productId = "id" // JSON ключ "id" мапится на productId
case productName = "name"
case inStock = "in_stock"
}
}
let json = """
{
"id": 101,
"name": "Laptop",
"in_stock": true
}
""".data(using: .utf8)!
let product = try? JSONDecoder().decode(Product.self, from: json)
print(product?.productName) // LaptopДля сложных случаев, когда автоматической генерации недостаточно (например, нужно преобразовать формат даты или обработать вложенные структуры), можно реализовать методы init(from:) и encode(to:) вручную.
struct CustomEvent: Codable {
var title: String
var timestamp: Date // Специальный формат даты
// Кастомный декодер
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
let dateString = try container.decode(String.self, forKey: .timestamp)
let formatter = ISO8601DateFormatter()
if let date = formatter.date(from: dateString) {
timestamp = date
} else {
throw DecodingError.dataCorruptedError(forKey: .timestamp, in: container, debugDescription: "Invalid date format")
}
}
// Кастомный энкодер
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(title, forKey: .title)
let formatter = ISO8601DateFormatter()
let dateString = formatter.string(from: timestamp)
try container.encode(dateString, forKey: .timestamp)
}
enum CodingKeys: String, CodingKey {
case title, timestamp
}
}Вывод: Используйте протокол Codable для сериализации и десериализации в Swift, так как это типобезопасный, эффективный и стандартный подход, поддерживаемый Foundation. Он идеально подходит для работы с JSON в сетевых слоях и для локального сохранения данных. Для нестандартных форматов или сложных преобразований реализуйте кастомную логику через CodingKeys или ручное кодирование/декодирование.