В предыдущей статье мы рассмотрели основы нового протокола Swift 4 Codable на примере кодирования структур и их миксов. В этой статье вы узнаете, как работать с Codable Date при кодировании и декодировании.
Давайте создадим простую структуру, как в прошлой статье, только добавим в нее свойство типа Date:
1 2 3 4 | struct Hotel : Codable { var name: String var bookingFor: Date } |
Теперь давайте создадим от структуры Hotel один экземпляр, заполним его, и закодируем в JSON, все как в прошлой статье, что бы увидеть, как это будет выглядеть:
1 2 3 4 5 6 7 8 9 10 | let hotel = Hotel( name: "Intercontinental", bookingDate: Date() ) let encoder = JSONEncoder() if let data = try? encoder.encode(hotel) { print(String(data: data, encoding: .utf8)!) } |
В лог будет выведен текст:
{«name»:»Intercontinental»,»bookingDate»:530568461.05150199}
В этом выводе отображено намного больше, чем может показаться на первый взгляд. А JSONEncoder, созданный ранее, поможет рассмотреть их получше с помощью своего функционала.
В данный момент нам необходим .dateEncodingStrategy. Да, это Swift энумератор (enum). с разными «вкусностями» внутри. Давайте посмотрим на них.
Вариант по умолчанию мы уже увидели в логе, называется он .defferedToDate. Еще один вариант называется .iso8606.
Декодеры имеют аналогичные свойства. Раньше, получая даты через HTTP API мы должны были подстраиваться под пришедшие типы, и иногда это было больно.
Давайте попробуем декодировать подобный болезненный формат даты. Все что нам понадобится — присвоить .formatted(DataFormatter) значение для свойства .dateDecodingStrategy нашего JSONDecoder.
У нас есть JSON для декодирования:
1 2 3 4 | { "name":"Intercontinental", "bookingDate":"Friday, Aug 18, 2017" } |
Далее создадим наш декодер и форматтер и попробуем с их помощью вывести в лог столь нестандартную дату:
1 2 3 4 5 6 7 8 9 10 11 | let decoder = JSONDecoder() let formatter = DateFormatter() formatter.dateFormat = "EEEE, MMM d, yyyy" decoder.dateDecodingStrategy = .formatted(formatter) let data = jsonString.data(using: .utf8)! if let data = try? decoder.decode(Hotel.self, from: data) { print(data) } |
Вот и все! Декодер в связке с форматтером привели нашу дату к формализованному виду:
Hotel(name: «Intercontinental», bookingDate: 2017-08-17 21:00:00 +0000)
Код из статьи вы можете посмотреть, перейдя по этой ссылке.
Удачного программирования!
Это все здорово. А как быть если мы в структуре имеем 2 даты в разном формате? Например: дата создания (со временем), дата заселения (без времени).
И вы показываете все время работу со структурами.
encoder.encode / decode не будет работатть с классами, если класс наследуется от другого например от базового класса Object (Realm).
как вы решаете эту проблему? Ведь зачастую нужно не просто сманить данные, но и сохранить их в БД в виде кэша