Стратегии декодирования ключей и дат
Используйте snake_case и стратегии работы с датами.
«Стратегии декодирования ключей и дат» — бесплатный урок Swift Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.
Обзор стратегий декодирования
Вместо того чтобы объявлять перечисление CodingKeys для каждого типа, Вы можете задать глобальную стратегию для декодера. Стратегии единообразно преобразуют ключи и разбирают даты во всех декодируемых типах.
import Foundation
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
print("Strategy configured")convertFromSnakeCase
Установка keyDecodingStrategy = .convertFromSnakeCase автоматически сопоставляет ключи вроде first_name со свойством camelCase firstName — CodingKeys не нужен.
import Foundation
struct User: Codable {
var firstName: String
var lastName: String
}
let json = "{\"first_name\":\"Ada\",\"last_name\":\"Lovelace\"}"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let u = try decoder.decode(User.self, from: json.data(using: .utf8)!)
print(u.firstName, u.lastName)Кодирование в snake_case
У encoder есть зеркальная настройка: keyEncodingStrategy = .convertToSnakeCase записывает свойства camelCase в JSON-ключи snake_case.
import Foundation
struct User: Codable {
var firstName: String
}
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(User(firstName: "Ada"))
print(String(data: data, encoding: .utf8)!)Стратегия применяется ко всем ключам
Стратегия ключей единообразно применяется к каждому свойству каждого вложенного типа. Это особенно удобно, когда весь программный интерфейс последовательно использует snake_case.
import Foundation
struct Meta: Codable { var createdAt: String }
struct Doc: Codable { var docTitle: String; var docMeta: Meta }
let json = "{\"doc_title\":\"A\",\"doc_meta\":{\"created_at\":\"now\"}}"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let d = try decoder.decode(Doc.self, from: json.data(using: .utf8)!)
print(d.docTitle, d.docMeta.createdAt)Проблема с датами
В JSON нет типа даты. Значения Date кодируются как числа или строки, и декодеру нужно знать их формат. dateDecodingStrategy указывает ему, как это сделать.
import Foundation
struct Event: Codable {
var name: String
var date: Date
}
print("Date needs a strategy to parse")Декодирование дат в формате ISO 8601
dateDecodingStrategy = .iso8601 разбирает стандартные метки времени ISO-8601, например 2020-01-01T00:00:00Z, в значения Date.
import Foundation
struct Event: Codable {
var name: String
var date: Date
}
let json = "{\"name\":\"Launch\",\"date\":\"2020-01-01T00:00:00Z\"}"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let e = try decoder.decode(Event.self, from: json.data(using: .utf8)!)
print(e.date.timeIntervalSince1970)Кодирование дат в формате ISO 8601
Зеркальная настройка encoder — dateEncodingStrategy = .iso8601, которая записывает значения Date как строки ISO-8601.
import Foundation
struct Event: Codable {
var name: String
var date: Date
}
let e = Event(name: "Launch", date: Date(timeIntervalSince1970: 1577836800))
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let data = try encoder.encode(e)
print(String(data: data, encoding: .utf8)!)Стратегия secondsSince1970
Если программный интерфейс передаёт временные метки Unix в виде чисел, используйте .secondsSince1970, чтобы интерпретировать их как секунды, прошедшие с начала эпохи.
import Foundation
struct Event: Codable {
var date: Date
}
let json = "{\"date\":1577836800}"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
let e = try decoder.decode(Event.self, from: json.data(using: .utf8)!)
print(e.date.timeIntervalSince1970)Пользовательские форматы дат
Для нестандартных форматов передайте DateFormatter через .formatted(_:). Это позволяет обрабатывать даты вроде 2020-01-01, в которых нет компонента времени.
import Foundation
struct Event: Codable { var date: Date }
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
fmt.timeZone = TimeZone(identifier: "UTC")
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(fmt)
let e = try decoder.decode(Event.self, from: "{\"date\":\"2020-01-01\"}".data(using: .utf8)!)
print(e.date.timeIntervalSince1970)Объединение стратегий
Стратегии ключей и дат можно задать одновременно для одного декодера. Так Вы обработаете программный интерфейс со snake_case и ISO-8601 без повторяющегося кода для отдельных типов.
import Foundation
struct LogEntry: Codable {
var eventName: String
var occurredAt: Date
}
let json = "{\"event_name\":\"login\",\"occurred_at\":\"2020-01-01T00:00:00Z\"}"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601
let entry = try decoder.decode(LogEntry.self, from: json.data(using: .utf8)!)
print(entry.eventName, entry.occurredAt.timeIntervalSince1970)Стратегия и CodingKeys
Глобальная стратегия удобна для единообразных программных интерфейсов. Если отличаются только несколько ключей или имена имеют нерегулярный вид, явное перечисление CodingKeys обеспечивает точный контроль каждого ключа. Их можно даже комбинировать.
import Foundation
struct Item: Codable {
var itemName: String
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let i = try decoder.decode(Item.self, from: "{\"item_name\":\"Pen\"}".data(using: .utf8)!)
print(i.itemName)Проверка: стратегии
Проверьте, насколько хорошо Вы поняли стратегии декодирования.
Итоги: стратегии ключей и дат
Вы научились глобально настраивать кодировщик:
keyDecodingStrategy = .convertFromSnakeCaseпреобразует snake_case в camelCase;.convertToSnakeCaseвыполняет обратное кодирование.dateDecodingStrategy = .iso8601разбирает метки времени ISO;.secondsSince1970и.formatted(_:)охватывают другие форматы.- Стратегии единообразно применяются ко всем вложенным типам.
- Используйте стратегии для единообразных программных интерфейсов, а
CodingKeys— для нерегулярных.
Часто задаваемые вопросы
Урок «Стратегии декодирования ключей и дат» бесплатный?
Да — полный текст урока «Стратегии декодирования ключей и дат» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.
Чему я научусь в уроке «Стратегии декодирования ключей и дат»?
Используйте snake_case и стратегии работы с датами. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Стратегии декодирования ключей и дат»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- CodingKeys для переименования
- Стратегии декодирования ключей и дат
- Ручные encode(to:) и init(from:)
- Декодирование неоднородного JSON