0Pricing
Swift Academy · Урок

Стратегии декодирования ключей и дат

Используйте 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 — локальная установка не требуется.

Все уроки этого курса

  1. CodingKeys для переименования
  2. Стратегии декодирования ключей и дат
  3. Ручные encode(to:) и init(from:)
  4. Декодирование неоднородного JSON
← Назад к Swift Academy