Login Sign Up
Advert
Your ad spot
Reserve this exclusive slot for the selected period.
Buy advertising →
Telegram community logo - Затишна Галера
Added 06 Jan 2025 🌐 UK

Затишна Галера

@Zatishna_Galera
Number of subscribers: 2 710
Photos: 1,500
Videos: 462
Links: 2,000
Description:
Голова Одеського центру розробки DataArt та Delivery Director, капітан Затишної Галери, ділитимуся: завданнями із співбесід (QA/Delivery/Management), статтями, вакансіями, новинами зі світу IT. Контакт: [email protected] ; Patreon: patreon.com/CozyGalley
Source

Затишна Галера | iOSКомпас 🧭1️⃣7️⃣3️⃣ Завдання 173Як правильно декодувати JSON у Swift ...

Telegram community logo - Затишна Галера Затишна Галера @Zatishna_Galera
407 Views/Reach 2026-09-23 08:26 Message №2977
#iOSКомпас 🧭
1️⃣7️⃣3️⃣ Завдання 173

Як правильно декодувати JSON у Swift для роботи з датою?


Доброго здровля мої любі друзі. З вами ваш незмінний ios розробник Сергій з @badlinkschannel.

Одна з найчастіших проблем під час роботи з API - дати. Здавалося б, що може піти не так? Але на практиці бекенд може надіслати timestamp, ISO-рядок, американський формат або взагалі щось своє. Swift без правильної настройки декодера просто поверне помилку. Розбираємося, які стратегії декодування є і коли яку застосовувати.

🔣 Що Swift робить за замовчуванням:
Стандартна стратегія .deferredToDate використовує нативне `Codable`-представлення Date. Саме таку пару форматів за замовчуванням використовують JSONEncoder і JSONDecoder, але в реальних API це трапляється рідко. Найчастіше сервер надсилає або Unix timestamp, або рядок в ISO 8601, або щось кастомне. І тут без явного вибору стратегії не обійтися.

🔣 Timestamp - секунди чи мілісекунди:
Якщо API віддає дату числом - це часто timestamp. Для секунд від 1970 року підходить .secondsSince1970, для мілісекунд - .millisecondsSince1970. Головне, щоб бекенд був послідовним: якщо в одному полі мілісекунди, а в іншому секунди - доведеться писати кастомну логіку.

🔣 ISO 8601 - вбудована підтримка:
Для дат на кшталт "2025-11-01T12:00:00Z" є готова стратегія .iso8601. У сучасному Foundation вона вже нормально працює і з fractional seconds. Але якщо сервер надсилає нестандартний ISO-формат або взагалі відхиляється від RFC 3339, декодування все одно може впасти. У таких випадках допомагає кастомний парсер або ISO8601DateFormatter з потрібними параметрами.

🔣 Кастомний DateFormatter:
Коли формат не вписується в стандартні стратегії, можна задати свій форматер:

let formatter = DateFormatter()

formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)

decoder.dateDecodingStrategy = .formatted(formatter)

Для фіксованого серверного формату важливо явно вказувати локаль і часовий пояс. Інакше форматер може враховувати налаштування користувача, календар або часовий пояс пристрою, і результат виявиться зовсім не таким, як ви очікували.

🔣 Коли форматів декілька:
Буває, що API в різних полях або навіть в одному полі надсилає дати в різних форматах. Наприклад, нові дані в ISO, старі - у timestamp. Або просто розробники бекенду не змогли домовитися.

У таких випадках виручає кастомна стратегія, де можна перевірити кілька варіантів і повернути першу успішно розпарсену дату:

decoder.dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()

if let timestamp = try? container.decode(Double.self) {
return Date(timeIntervalSince1970: timestamp)
}

let string = try container.decode(String.self)

for formatter in formatters {
if let date = formatter.date(from: string) {
return date
}
}

throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Невідомий формат дати: \(string)"
)
}

Уся логіка залишається в одному місці, а не розмазується по моделях.

#️⃣ Дати - одне з тих місць, де декодинг може впасти в найнесподіваніший момент. Хороша новина: Swift дає гнучкі інструменти, щоб розрулити майже будь-яку ситуацію. Погана: про них потрібно знати й застосовувати усвідомлено. Універсальної стратегії немає, але правильно налаштований декодер врятує від купи багів на проді.

@Zatishna_Galera