В экосистеме Scala довольно много библиотек для работы с json, включая стандартную и исключая java-библиотеки. Данный пост начинает серию статей по использованию различных библиотек для работы с json в Scala. Эта серия статей не претендует на полноценный охват всех возможных библиотек или всех возможностей в библиотеках. Основная цель - понять как работать с json при помощи нескольких популярных библиотек.
Для рассмотрения предполагается следующий список (порядок случайный):
Статья | Библиотека | Описание |
---|---|---|
play json | Play Json | Библиотека для работы с json выделенная из популярного web framework’а - Play |
Spray Json | Библиотека выделенная из проекта spray (инструментарий для организации REST/HTTP слоя поверх akka). | |
Argonaut | Библиотека использующая в своей основе только функциональную парадигму, то есть pure functional by design, активно использует ScalaZ. |
Обновление К сожалению, нет времени закончить эту серию и написать все запланированные посты. Тем не менее, все запланированные библиотеки были рассмотрены в коде, который можно посмотреть на github - https://github.com/algolov/JsonSeries.git
В конце серии планируется заключительный пост со сравнением всех библиотек. В качестве сквозного примера будет использоваться список ссылок с сайта reddit.com в json, конкретно Scala subreddit. В данном посте я опишу каркас, который будет использоваться при описании каждой из библиотек.
Каркас приложения
Если посмотреть на описание json объектов возвращаемых JSON API reddit’a, то мы увидим, что для представления длинного содержимого используются объекты Listing
, которые имеют три основных поля: before
, after
и data
. Первые два служат для указания элемента в листинге с которого начинать разделение. А вот поле data
как раз содержит список элементов, которые оборачивает данный листинг, в нашем примере это будут ссылки в сабреддите Scala. Так как основная цель это сравнить различные json библиотеки, а не написать свой клиент для reddit.com все модели предельно упрощены и заточены на то, чтобы показать различные сценарии работы с json. Итак, класс представляющий листинг:
1 2 3 4 5 |
|
Поле id было добавлено просто для того, что бы смоделировать сценарий, когда в модели есть поля, которые не должны быть сериализованны, но должны быть заданы при десериализации. Можно представить, что мы хотели бы хранить экземпляры листингов для каких-нибудь своих загадочных целей и различать их по uuid.
Следующий класс Link
, представляющий ссылку:
1 2 3 4 |
|
Оригинальный объект Link
содержит гораздо большее количество полей, но нам вполне хватит нескольких. Последнее поле - stats, представляет собой различную количественную информацию о ссылке, выделенную в отдельный класс:
1 2 3 4 5 |
|
Итак, представленный набор классов позволит рассмотреть распространенные сценарии работы с json. Теперь перейдем к описанию рассматриваемой функциональности json библиотек. Вся функциональность выливается в четыре абстрактных метода трейта JsonLibrary
:
1 2 3 4 5 6 7 |
|
Так как каждая библиотека для кодирования понятия JSON имеет свой конкретный тип, то в трейте присутствует абстрактное поле, представляющее этот тип (abstract type member): type JSON
. Каждая рассматриваемая библиотека будет расширять данный трейт, конкретизируя какой тип будет использоваться в качестве представления JSON и реализовывать весь набор операций в соответствии со своим API.
Для того, что бы получить начальное строковое представление json с которым будет вестись работа, напишем вспомогательный метод, который будет считывать соответствующие данные с сайта www.reddit.com или из заранее подготовленного локального файла, расположенного в ресурсах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Параметры данного метода позволяют “пролистать” листинги, указав направление и количество просмотренных ссылок (см. reddit api). И для того что бы удостоверится, что все работает верно - напишем несколько тестов, для этого будет использоваться замечательный тестовый фреймворк ScalaTest.
1 2 3 |
|
Трейт UnitJsonSpec
является базовым трейтом. Он смешивает общие для всех спецификаций трейты и загружающий текст с json.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Трейт JsonLibraryFunctionalitySpec
это спецификация содержащая тесты основной функциональности библиотек. Все спецификации рассматриваемых библиотек расширяют данную спецификацию, реализуя метод name и наследуя все тесты, а так же примешивают конкретную реализацию JsonLibrary
для переопределения абстрактных методов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
JsonLibraryPerfomanceSpec
спецификация, содержащая тесты производительности json библиотек. Данные тесты, как и тесты обзорной функциональности, не претендуют на какой-либо серьезный бэнчмаркинг и добавлены лишь для поверхностного сравнения. Так что, если интересует серьезный тест производительности json библиотек, то не стоит принимать в расчет цифры полученные в результате этих тестов.
Исходники и запуск
Исходные тексты можно найти в соответствующем репозитории на github. Для запуска необходимо клонировать репозиторий, зайти в директорию JsonSeries и в командной строке выполнить команду sbt test
. Для того, что бы запустить только тесты производительности нужно выполнить следующую команду: sbt "test-only *PerfomanceSpec"
по этому же принципу можно указать и тесты конкретных библиотек или просмотреть только тесты функциональности. Данные команды загрузят необходимые зависимости, скомпилируют исходные файлы и запустят тесты на выполнение.