- Шпаргалка Java программиста 8. Библиотеки для работы с Json (Gson, Fastjson, LoganSquare, Jackson, JsonPath и другие)
- 8. Работа с Json
- 1. JSON парсеры
- 1.1 Обзор библиотек
- 1.2 Простейшие примеры использование Data bind
- Android: парсим JSON правильно
- Сериализация от Kotlin
- Сериализация от Kotlin + Retrofit
- Сериализация от Kotlin
- Сериализация от Kotlin + Retrofit
Шпаргалка Java программиста 8. Библиотеки для работы с Json (Gson, Fastjson, LoganSquare, Jackson, JsonPath и другие)
В одной из моих прошлых статей я рассказывал о своем opensorce pet проекте useful-java-links, идея которого собрать как можно больше ссылок на полезные Java библиотеки и фреймворки. У него так же есть подпроект Hello World project идея которого для каждой библиотеки собрать несколько простых примеров её использования.
Проблема программистов в Java мире в том что кроме стандартной библиотеки JDK есть огромное других полезных библиотек, причем переход от одной библиотеки к другой может вызывать проблемы из-за неполной документации, отсутствия простых примеров или даже сложности понять какие зависимости нужно добавить в maven чтобы все запустилось. А на новой работе вполне могут использовать вместо твоей любимой библиотеки ту которую ты не знаешь. Идея моего проекта облегчить изучение и выбор разных библиотек.
Итак, давайте посмотрим какие известные библиотеки есть для работы с JSON в Java…
8. Работа с Json
JSON парсеры
Аналог XPath для JSON
Генерация Java классов из JSON или JSON схемы и JSON валидация
Итак, у нас восемь библиотек для сериализации и десериализации в json, две библиотеки для генерации Java классов по схеме или json файлу, одна библиотека для валидации схемы и два аналога XPath, но для json. Давайте рассмотрим каждую из них.
1. JSON парсеры
Существует три основных способа сериализации и десериализации среди указанных библиотек (от самого простого к самому сложному) и один дополнительный:
- Data bind,
- Tree Model,
- Streaming API,
- (И дополнительный способ) Аналоги XPath,
Давайте рассмотрим с чем их едят:
Data bind самый популярный и простой способ, вы просто указываете класс, который нужно преобразовать в json, может быть часть полей отмечаете аннотациями (а зачастую даже это необязательно), а библиотека сама превращает этот класс и всю его иерархию классов в json. Аналогом при работе с xml будет JAXB (Java Architecture for XML Binding)
Плюсы: наиболее простой из всех, по сути главное реализовать только Java классы, более того можно просто сгенерировать Java классы из json’a или json схемы.
Минусы: скорость и память. Большинство библиотек использует рефлексию и т.п. методы работы с Java классами (хотя не все), что очевидно не очень быстро. К тому же, весь json файл сразу превращается в Java объекты, что может просто исчерпать всю доступную память, если вы попытаетесь обработать очень большой json.
Вывод: если нет проблем с производительностью, памятью и вы не собираетесь обрабатывать многогигабайтные json’ы скорее всего самый лучший способ.
Tree Model — данный парсер представляет json в виде Java классов таких как Node или JsonElement c иерархической структурой, а уже сам программист их обходит и получает из них информацию. Данный способ похож на DOM парсеры в xml.
Плюсы: обычно быстрее первого способа и проще третьего,
Минусы: уступает Data bind по простоте, плюс ряд библиотек способен генерить классы при Data bind, а не использовать рефлексию, в этом случае то что Tree Model будет быстрее не очевидно, к тому же не решается проблема огромных файлов и ограничения памяти.
Streaming API — самый низкоуровневый способ, по сути программист сам вручную разбирает токены json’a. Зато никаких ограничений по памяти и в теории максимальная производительность.
Плюсы: производительность и минимальное потребление памяти,
Минусы: сложность использования,
Аналоги XPath — дополнительный способ, не очень подходит, если нужно получит всю информацию из json’a, зато позволяет написав выражение $.store.book[*].author и получить список всех авторов всех книг из json’a магазина. То есть легко получать часть информации из json’а.
Плюсы: позволяет быстро получить информацию из json’а по сложным критериям,
Минусы: не очень подходит, когда нужна все информация из json’а, не работает в обратную сторону на формирования json’ов,
1.1 Обзор библиотек
Способ | Fastjson | Gson | LoganSquare | JSON java | Moshi | Ig json parser | Jackson | Genson | JsonPath |
---|---|---|---|---|---|---|---|---|---|
1. Data bind | Да | Да | Да | — | Да | Да | Да | Да | — |
2. Tree Model | — | Да | — | Да | — | — | Да | — | — |
3. Streaming API | — | Да | — | — | — | — | Да | — | — |
4. Аналоги XPath | Да | — | — | — | — | — | — | — | Да |
5. Генерация классов для Data bind* | — | — | Да | — | — | Да | — | — | — |
6. Github’s star | 4851 | 4120 | 2188 | 1937 | 1732 | 921 | 881 | 108 | 849 |
7. Работает со static inner class** | Да | Да | Нет | — | Да | Нет | Да | Да | — |
8. Обязательность аннотаций*** | Нет | Нет | Да | — | Нет | Да | Нет | Нет | — |
По ссылкам на Да можно найти примеры использования.
* — Генерация классов для Data bind позволяет сгенерировать классы на стадии компиляции, что в теории должно давать значительный прирост производительности библиотеки,
** — Работает со static inner class имеет смысл только для случая Data bind, возможно ли сериализация и десериализация для случая статических внутренних классов (не статические внутренние классы сериализовать не рекомендуется),
*** — тоже только для случая Data bind можно ли не использовать аннотации или их использование крайне рекомендуется,
1.2 Простейшие примеры использование Data bind
Для демонстрации работы библиотек будем использовать следующий json:
И следующие Java классы (в разных примерах могут слегка отличаться наличием аннотаций, если они обязательны):
Как можно увидеть, Java классы всего лишь состоять из двух классов Human и Place, в которых храниться сообщение Hi World. Json тоже содержит эти два вложенных объекта.
Примеры использования (Data bind): Способ | Fastjson | Gson | LoganSquare | Moshi | Ig json parser | Jackson | Genson |
---|---|---|---|---|---|---|---|
Инициализация | — | Gson gson = new Gson() | — | Moshi moshi = new Moshi. Builder().build(); JsonAdapter jsonAdapter = moshi.adapter(Human.class) | — | ObjectMapper mapper = new ObjectMapper() | Genson genson = new Genson() |
Из Java в json | JSON.toJSONString(human) | gson.toJson(human) | LoganSquare.serialize(human) | jsonAdapter.toJson(human) | Human__JsonHelper.serializeToJson(human) | mapper.writeValueAsString(human) | genson.serialize(human) |
Из json в Java | JSON.parseObject(jsonString, Human.class) | gson.fromJson(jsonString, Human.class) | LoganSquare.parse(jsonString, Human.class) | jsonAdapter.fromJson(jsonString) | Human__JsonHelper.parseFromJson(jsonString) | mapper.readValue(jsonString, Human.class) | genson.deserialize(jsonString, Human.class) |
Human__JsonHelper — это класс который Ig json parser сгенерировал на этапе компиляции, у LoganSquare так же есть генерации на этапе компиляции, но там классы подключаются «под капотом» внутри LoganSquare.
Источник
Android: парсим JSON правильно
Любой Android-разработчик рано или поздно сталкивается с форматом представления данных типа JSON. Наиболее часто он используется для передачи/получения данных с какого-либо сервера. Формат предельно прост, подробнее о нём можно почитать в Википедии:
«JSON (JavaScript Object Notation, обычно произносится как /ˈdʒeɪsən/ JAY-sən) — текстовый формат обмена данными, основанный на JavaScript. Как и многие другие текстовые форматы, JSON легко читается людьми. Несмотря на происхождение от JavaScript, формат считается независимым от языка и может использоваться практически с любым языком программирования. Для многих языков существует готовый код для создания и обработки данных в формате JSON».
Любой класс в Java или Kotlin можно представить в виде структуры JSON, где есть поля, атрибуты, фигурные скобки обозначают объект, квадратные скобки — массив.
Следующий пример показывает JSON-представление данных об объекте, описывающем человека. В данных присутствуют строковые поля имени и фамилии, информация об адресе и массив, содержащий список телефонов. Как видно из примера, значение может представлять собой вложенную структуру:
Наиболее популярный среди разработчиков способ трансформировать данные в JSON и обратно — это библиотека GSON от самих разработчиков Google. Она очень проста в использовании, мало весит и интегрирована во многие библиотеки.
На данный момент все, за редким исключением, Android-разработчики используют Kotlin, а GSON (как и другие подобные библиотеки типа Jackson или Moshi) написана на Java. Это не страшно, потому что Kotlin и Java полностью взаимозаменяемы, но есть небольшие нюансы, которые могут привести к совершенно неожиданным результатам.
Давайте создадим класс User и посмотрим на эти нюансы на практике. В этом классе у нас будут обычные поля и поля со значениями по умолчанию. Как вы знаете, в Java нельзя присваивать переменным значения по умолчанию, а в Kotlin можно:
И теперь представим, что с какого-то сервера пришли данные о пользователе в формате JSON:
Теперь нам нужно распарсить этот JSON и превратить его в обычный класс Kotlin с помощью библиотеки GSON. Добавим зависимость GSON в наш проект в файл Gradle
и сразу напишем тест:
Тест прекрасно выполняется без единой ошибки, то есть код работает. Но обратите внимание, что возраст пользователя у нас == 0, а его роль не определена, хотя в самом классе у нас прописаны значения по умолчанию для этих переменных. Если эти параметры не определены в JSON, должны подставляться значения по умолчанию: возраст == 13, а роль == Viewer, но они не подставляются, а код всё равно работает. Вот так неожиданность! Не такого поведения мы ожидали!
Давайте разбираться. Дело в том, что, как мы писали выше, библиотека GSON написана на Java, а это значит, что значения по умолчанию для несуществующих полей такие: для примитива int — это 0, для отсутствующего объекта — это null. Простая трансформация JSON в класс на Kotlin может легко сломать null-safety, на который так рассчитывают все разработчики, и может привести к падению приложения там, где оно падать не должно.
И тут нам на помощь приходит котлиновская библиотека по сериализации объектов.
Сериализация от Kotlin
Это небольшая вспомогательная библиотечка от разработчиков языка, которая работает с помощью аннотации @Serializable. С ней у вас не будет проблем при использовании полей по умолчанию. Чтобы подключить библиотеку к своему проекту, нужно прописать в файле Gradle плагин и несколько зависимостей. В файле проекта build.gradle(Project):
В файле проекта build.gradle(Module:app):
Теперь трансформация JSON (сериализация) будет проходить корректно. Напишем наш класс и добавим аннотацию:
Тест пройден успешно! Теперь класс сериализуется у нас со значениями по умолчанию, если таковые прописаны в классе.
Сериализация от Kotlin + Retrofit
Если вы хоть раз отправляли запрос на сервер или получали с сервера какой-то ответ, то наверняка вы знакомы с библиотекой Retrofit. В этой библиотеке нет поддержки сериализации от Kotlin, но у вас есть возможность добавить вспомогательную библиотеку от Джека Вортона в качестве зависимости Gradle:
Теперь при использовании Retrofit сериализация будет происходить автоматически:
Дополнительно, но не обязательно вы можете использовать JsonConfiguration для выключения StrictMode. StrictMode включен по умолчанию и запрещает использование неизвестных ключей в JSON и нечисловые значения в числах с плавающей точкой. Хорошая практика — включать StrictMode в «дебажной» версии приложения и выключать его в «релизной».
Читайте больше полезных статей для начинающих Android-разработчиков:
А если затянет — приходите на факультет Android-разработки. В время учебы вы разработаете Android-приложение и выложите его в Google Play, даже если никогда не программировали. А также своите языки Java и Kotlin, командную разработку, Material Design и принципы тестирования.
Любой Android-разработчик рано или поздно сталкивается с форматом представления данных типа JSON. Наиболее часто он используется для передачи/получения данных с какого-либо сервера. Формат предельно прост, подробнее о нём можно почитать в Википедии:
«JSON (JavaScript Object Notation, обычно произносится как /ˈdʒeɪsən/ JAY-sən) — текстовый формат обмена данными, основанный на JavaScript. Как и многие другие текстовые форматы, JSON легко читается людьми. Несмотря на происхождение от JavaScript, формат считается независимым от языка и может использоваться практически с любым языком программирования. Для многих языков существует готовый код для создания и обработки данных в формате JSON».
Любой класс в Java или Kotlin можно представить в виде структуры JSON, где есть поля, атрибуты, фигурные скобки обозначают объект, квадратные скобки — массив.
Следующий пример показывает JSON-представление данных об объекте, описывающем человека. В данных присутствуют строковые поля имени и фамилии, информация об адресе и массив, содержащий список телефонов. Как видно из примера, значение может представлять собой вложенную структуру:
Наиболее популярный среди разработчиков способ трансформировать данные в JSON и обратно — это библиотека GSON от самих разработчиков Google. Она очень проста в использовании, мало весит и интегрирована во многие библиотеки.
На данный момент все, за редким исключением, Android-разработчики используют Kotlin, а GSON (как и другие подобные библиотеки типа Jackson или Moshi) написана на Java. Это не страшно, потому что Kotlin и Java полностью взаимозаменяемы, но есть небольшие нюансы, которые могут привести к совершенно неожиданным результатам.
Давайте создадим класс User и посмотрим на эти нюансы на практике. В этом классе у нас будут обычные поля и поля со значениями по умолчанию. Как вы знаете, в Java нельзя присваивать переменным значения по умолчанию, а в Kotlin можно:
И теперь представим, что с какого-то сервера пришли данные о пользователе в формате JSON:
Теперь нам нужно распарсить этот JSON и превратить его в обычный класс Kotlin с помощью библиотеки GSON. Добавим зависимость GSON в наш проект в файл Gradle
и сразу напишем тест:
Тест прекрасно выполняется без единой ошибки, то есть код работает. Но обратите внимание, что возраст пользователя у нас == 0, а его роль не определена, хотя в самом классе у нас прописаны значения по умолчанию для этих переменных. Если эти параметры не определены в JSON, должны подставляться значения по умолчанию: возраст == 13, а роль == Viewer, но они не подставляются, а код всё равно работает. Вот так неожиданность! Не такого поведения мы ожидали!
Давайте разбираться. Дело в том, что, как мы писали выше, библиотека GSON написана на Java, а это значит, что значения по умолчанию для несуществующих полей такие: для примитива int — это 0, для отсутствующего объекта — это null. Простая трансформация JSON в класс на Kotlin может легко сломать null-safety, на который так рассчитывают все разработчики, и может привести к падению приложения там, где оно падать не должно.
И тут нам на помощь приходит котлиновская библиотека по сериализации объектов.
Сериализация от Kotlin
Это небольшая вспомогательная библиотечка от разработчиков языка, которая работает с помощью аннотации @Serializable. С ней у вас не будет проблем при использовании полей по умолчанию. Чтобы подключить библиотеку к своему проекту, нужно прописать в файле Gradle плагин и несколько зависимостей. В файле проекта build.gradle(Project):
В файле проекта build.gradle(Module:app):
Теперь трансформация JSON (сериализация) будет проходить корректно. Напишем наш класс и добавим аннотацию:
Тест пройден успешно! Теперь класс сериализуется у нас со значениями по умолчанию, если таковые прописаны в классе.
Сериализация от Kotlin + Retrofit
Если вы хоть раз отправляли запрос на сервер или получали с сервера какой-то ответ, то наверняка вы знакомы с библиотекой Retrofit. В этой библиотеке нет поддержки сериализации от Kotlin, но у вас есть возможность добавить вспомогательную библиотеку от Джека Вортона в качестве зависимости Gradle:
Теперь при использовании Retrofit сериализация будет происходить автоматически:
Дополнительно, но не обязательно вы можете использовать JsonConfiguration для выключения StrictMode. StrictMode включен по умолчанию и запрещает использование неизвестных ключей в JSON и нечисловые значения в числах с плавающей точкой. Хорошая практика — включать StrictMode в «дебажной» версии приложения и выключать его в «релизной».
Читайте больше полезных статей для начинающих Android-разработчиков:
А если затянет — приходите на факультет Android-разработки. В время учебы вы разработаете Android-приложение и выложите его в Google Play, даже если никогда не программировали. А также своите языки Java и Kotlin, командную разработку, Material Design и принципы тестирования.
Источник