Введение в json со свифтом. Часть 2.

rom
rom
Aug 26, 2017 · 4 min read

Всем привет!

Как и было обещано в предыдущем посте, сегодня мы с вами распарсим JSON, но уже без сторонних библиотек, а руками. 😱

На самом деле, ужасно давно уже этого не делал. 😅

Хотя, наверное, зря. Иногда мы привыкаем, что для всего можно просто добавить очередную библиотеку и сделать все “быстро и просто”, хотя это лишние зависимости и вообще.

Поэтому, сегодня будут только методы из Foundation, только хардкор, поехали! 🚀

Для того, чтобы пройти этот туториал, вам понадобится Xcode beta 9 со swift 4 на борту, скачать ее можно, зарегистрировавшись на портале для разработчиков Apple, вот здесь. А также я подготовил стартовый и законченный проекты. Их можно скачать тут.

Итак, открываем стартовый playground project, и все, что мы там можем обнаружить, это

А еще там есть, если зайти в папку Resourses, test.json.

Читаем JSON

Для начала нам стоит этот json прочитать. Для этого необходимо создать метод getJSON.

Далее стоит добавить путь до JSON файла. Так как путь у нас будет optional, я раскрою его безопасным образом через if let. Можно сразу отметить, что так как мы уверены, что JSON существует, в этом нет большой необходимости, просто я так привык 😄

Далее стоит получить объект data из полученного пути. Для этого добавим do-catch блок, внутри которого получим объект data, а если получить его не получится, выведем ошибку.

Большая часть пути уже позади, осталось только получить из объекта data наш JSON, который в свифте описывается как [String: Any]. Для этого нам нужно вызвать привычный со времен Objective-C JSONSerialization на data:

Объединенный код будет выглядеть так (в конце просто вызовем этот метод):

Ура, мы получили json и можем видеть его содержимое в дебаггере 😄

Осталось добавить класс пользователя, чтобы распарсить его 🙃

Добавим класс User в наш Playground, и, могу обрадовать, этот класс не будет сильно отличаться от того, который мы написали в прошлый раз:

Собственно, все, что здесь действительно изменилось, так это то, что вместо типа JSON мы используем [String: Any]?.

Метод парсера тоже не особо изменился:

Изменения здесь только синтаксические, потому как .string в SwiftyJSON делал то же самое, что здесь делает as? String.

Осталось немного изменить наш getJSON в Playground. Для начала вернем пользователя.

Далее удаляем строку print(json) и добавляем вместо нее:

А если if let path не сработал, то просто вернем nil. Таким образом, наш метод приобретает следующий вид:

Осталось отпринтовать пользователя и поздравить себя с тем, что мы распарсили очередной JSON 🎉🎉🎉

Примерно так мы парсили JSON до всех этих наших хипстерских библиотек во времена старого доброго Objective-C. И каждый раз это выглядело немного странно и вообще akward. Мы получаем валидный JSON, превращаем его в Data, потом в [String: Any] (или в [String: AnyObject]), а потом в обработанный объект. И к релизу swift 4 Apple решил-таки ответить на вопрос, как они видят парсинг JSON.

Видят очень круто 😎

Пишем SwiftyParse

В том же playground файле создадим новый метод getSwiftyJSON(), туда перенесем наш if let path, do-catch блоки и data. Метод должен выглядеть так:

А теперь начинается магия Swift 4 🎩

Создадим объект decoder и добавим еще один do-catch блок:

Как можно догадаться, внутри этого do-catch блока мы и будем получать пользователя. Вот только происходить это будет совсем иначе 😁

Вот и все!

Осталось создать класс SwiftyUser, и попробуйте догадаться, в чем разница с предыдущим методом 🤔

Новый класс выглядит следующим образом:

И все, если мы захотим отпринтовать полученного пользователя, мы получим то же самое, что раньше делали через JSONSerialization.jsonObject!

При этом здесь нет никаких инициализаторов! (Можете проверить и добавить, метод init не вызывается.) Декодер сам пробегает по JSON файлу и сравнивает его с тем, что мы ему предлагаем в качестве объекта декодинга! Магия! 🎩

А как же быть со вложенными объектами?

Да прямо так и быть!

Как вы могли заметить, у нас там есть объект Location: Добавим его к SwiftyUser:

И вуаля, локация добавлена! Но, подождите, там же не хватает country.

И вот здесь кроется минус такого метода. Для каждого вложения, сообщает нам Apple, лучше создавать отдельный struct/class/enum. В данном случаем мы создадим countryObj:

Осталось вернуть пользователя. Для этого изменим метод следующим образом:

И отпринтуем пользователя, думаю, вы уже знаете, как это делать. 😏

Поздравляю, вы только что разобрались, как модно-хипстерски парсить JSON в Swift 4! 😎🎉🎉🎉🎉🎉🎉

Да, к этому новому методу нужно привыкнуть, но у него множество возможностей для кастомизации, пусть они и не всегда очевидные. А ведь это и правда круто — парсить json безо всех этих бесконечных if let. Или не круто 🤔

В любом случае, буду рад услышать мнение в комментах 😆

Ох, пост вышел несколько длиннее, чем планировалось, но, надеюсь, вам не было скучно, и вы узнали что-то новое. В любом случае, лайк-репост 😄

Photo by Luke Chesser on Unsplash

)

rom

Written by

rom

swift/obj-c, ruby, c/c++, software engineering. So amazing, very bleeding edge.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade