Что происходит при ошибке декодера и узнаем ли мы о проблеме с декодированием модели в Swift?
Что проверяют
Знаете ли вы, что декодирование в Swift бросает ошибку, а не возвращает пустую модель, и понимаете ли, в каких случаях проблема, наоборот, проходит молча. Это про умение разбирать баг «данные с сервера пришли, а экран пустой».
Как отвечать
JSONDecoder.decode помечен throws и при несовпадении данных с моделью бросает DecodingError. У него четыре случая, каждый называет причину:
keyNotFound: в JSON нет обязательного ключа;typeMismatch: тип не тот, например число пришло строкой;valueNotFound: пришёлnullтам, где ожидался неопциональный тип;dataCorrupted: данные не разбираются вовсе либо не подходят под стратегию дат.
Главное, что стоит показать: у ошибки есть контекст с codingPath, то есть путь до конкретного поля. Его и логируют, иначе в отчёте будет бесполезное «не удалось разобрать ответ».
do {
let user = try JSONDecoder().decode(User.self, from: data)
} catch let error as DecodingError {
log(String(describing: error)) // путь до поля и причина
}Отдельно назовите случай, когда ошибки не будет: опциональное поле при отсутствующем ключе декодируется в nil молча. Это удобно, но именно так теряют данные после переименования поля на бэкенде, поэтому нужные логике поля опциональными не делают.
Где спотыкаются
Пишут try? и теряют причину целиком. Модель становится nil, экран пустой, в логах ничего. try? уместен, только когда провал ожидаем и обработан, в остальных случаях нужен разбор ошибки в catch.
Второе: не учитывают, что один плохой элемент роняет весь массив. Если в списке из сотни объектов у одного сломан тип поля, декодер вернёт ошибку на всю коллекцию. Когда терять элементы допустимо, пишут обёртку, которая декодирует массив поэлементно.
Третье: считают, что раз ошибки нет, модель заполнена. С россыпью опциональных полей декодер успешно отработает и на пустом объекте. Проверять надо не факт успеха, а наличие того, что реально нужно экрану.