Как работать с json в java
Для работы с JSON в Java часто используют библиотеку Jackson . Она позволяет с легкостью преобразовывать объекты Java в JSON и наоборот.
Пример чтения JSON-файла :
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; public class JsonExample public static void main(String[] args) ObjectMapper mapper = new ObjectMapper(); try // читаем JSON-файл в объект MyObject obj = mapper.readValue(new File("file.json"), MyObject.class); // выводим содержимое объекта на консоль System.out.println(obj.toString()); > catch (IOException e) e.printStackTrace(); > > >
В данном примере создается объект ObjectMapper , который отвечает за преобразование между объектами Java и JSON . Затем метод readValue используется для чтения содержимого файла «file.json» и преобразования его в объект класса MyObject
Пример записи JSON-файла :
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; public class JsonExample public static void main(String[] args) ObjectMapper mapper = new ObjectMapper(); try // создаем объект MyObject obj = new MyObject("value1", "value2", 123); // записываем объект в файл в формате JSON mapper.writeValue(new File("file.json"), obj); > catch (IOException e) e.printStackTrace(); > > >
Как и чем парсить Json на Java?
Часто возникает потребность работы с Json, в частности его чтения и парсинга. В Java обычно ты знаешь с каким типом переменных работаешь, а при парсинге Json смущает то, что тип полей может быть любой. Какие есть способы разбора Json? Как это делать? Вот, допустим, как достать данные из Json, представленного ниже?
< "firstName": "Json", "lastName": "Smith", "age": 30, "address": < "streetAddress": "666 1nd Street", "city": "New York", "state": "NY", "postalCode": 10021 >, "phoneNumbers": [ < "type": "home", "number": "542 666-1234" >, < "type": "fax", "number": "653 666-4567" >], "friends": [ < "firstName": "Test", "lastName": "Snow", "age": 20, "phoneNumbers": [ < "type": "home", "number": "141 111-1234" >], "friends": [ < "firstName": "UnknownFirstName", "lastName": "UnknownLastName", "age": 999, "phoneNumbers": [ < "type": "home", "number": "000 000-0000" >] > ] >, < "firstName": "Flash", "lastName": "Tompson", "age": 23, "phoneNumbers": [ < "type": "home", "number": "999 111-1234" >] > ] >
Отслеживать
28.5k 12 12 золотых знаков 58 58 серебряных знаков 118 118 бронзовых знаков
задан 15 ноя 2017 в 13:35
Алексей Шиманский Алексей Шиманский
71.1k 12 12 золотых знаков 90 90 серебряных знаков 180 180 бронзовых знаков
4 ответа 4
Сортировка: Сброс на вариант по умолчанию
Достать данные можно разными способами и, конечно, зависит от задач. Попробую рассмотреть некоторые варианты разбора Json.
Заметка: для каждого из примеров для парсинга будет взят Json из вопроса, чтобы зря не копировать в ответ.
Simple Json
Где взять: здесь / репозиторий на github / или через Maven и пр.
Это самый примитивный способ. По сути, всё, что тут есть — это JSONObject и JSONArray .
- JSONArray может включать в себя несколько объектов JSONObject , его можно обходить циклом на каждой итерации получая объект JSONObject .
- JSONObject — объект, из которого можно доставать его отдельные свойства.
Я бы использовал его для небольших Json строк, где не надо сильно заморачиваться или если не лень писать свой класс-обработчик на основе кода, который продемонстрирован ниже:
// Считываем json Object obj = new JSONParser().parse(jsonString); // Object obj = new JSONParser().parse(new FileReader("JSONExample.json")); // Кастим obj в JSONObject JSONObject jo = (JSONObject) obj; // Достаём firstName and lastName String firstName = (String) jo.get("firstName"); String lastName = (String) jo.get("lastName"); System.out.println("fio: " + firstName + " " + lastName); // Достаем массив номеров JSONArray phoneNumbersArr = (JSONArray) jo.get("phoneNumbers"); Iterator phonesItr = phoneNumbersArr.iterator(); System.out.println("phoneNumbers:"); // Выводим в цикле данные массива while (phonesItr.hasNext())
Остальная работа с вложенными массивами аналогична. Можно складывать в List, Map и пр.
GSON
Где взять: здесь / репозиторий на github / или через Maven и пр.
Позволяет парсить Json также, как и Json-simple, т.е. используя JSONObject и JSONArray (см. документацию), но имеет более мощный инструмент парсинга. Достаточно создать классы, которые повторяют структуру Json‘а. Для парсинга Json из вопроса создадим классы:
class Person < public String firstName; public String lastName; public int age; public Address address; public ListphoneNumbers; public List friends; > class Address < public String streetAddress; public String city; public String state; public int postalCode; >class Phones
Теперь достаточно написать:
Gson g = new Gson(); Person person = g.fromJson(jsonString, Person.class);
Всё! Магия! Чудо! Теперь в person лежит объект с типом Person , в котором находятся данные именно с теми типами, которые были указаны в созданных классах! Теперь можно работать с любым типом, как это привыкли всегда делать: String, Integer, List, Map и всё остальное.
// Выведет фамилии всех друзей с их телефонами for (Person friend : person.friends) < System.out.print(friend.lastName); for (Phones phone : friend.phoneNumbers) < System.out.println(" - phone type: " + phone.type + ", phone number : " + phone.number); >> // output: // Snow - phone type: home, phone number : 141 111-1234 // Tompson - phone type: home, phone number : 999 111-1234
Пример парсинга в Map :
. JSON для разбора:
< "2":< "sessions":[ < "time":"13:00", "price":"410" >, < "time":"06:40", "price":"340" >, < "time":"16:50", "price":"370" >], "name":"Кинокис-L", "locate":"Москва, Садовая-Спасская ул., 21, 56", "metro":"Красные ворота" >, "7":< "sessions":[ < "time":"06:35", "price":"190" >, < "time":"00:05", "price":"410" >], "name":"Кинокис-V", "locate":"Павелецкая пл., 2, строение 1", "metro":"Павелецкая" >, "8": < "sessions":[ < "time":"15:10", "price":"330" >], "name":"Кинокис-J", "locate":"ул. Пречистенка, 40/2", "metro":"Кропоткинская" >, "9":< "sessions":[ < "time":"13:00", "price":"600" >, < "time":"08:30", "price":"300" >, < "time":"04:00", "price":"510" >, < "time":"13:15", "price":"340" >], "name":"Кинокис-U", "locate":"Шарикоподшипниковская ул., 24", "metro":"Дубровка" > >
class Seanse < public String name; public String locate public String metro; public Listsessions; > class Sessions
. Сам разбор выглядит так:
Gson g = new Gson(); Type type = new TypeToken>()<>.getType(); Map myMap = g.fromJson(json, type);
Дополнительно в GSON можно использовать аннотации, например: исключить указанные поля при парсинге, поменять имя переменной (например не personFirstName , а fName ) и многое другое. Подробнее см. в документации.
Jackson
Где взять: здесь / репозиторий на github / или через Maven и пр.
Как и GSON он также позволяет работать используя JSONObject и JSONArray если это требуется, и тоже умеет парсить на основе предоставленных классов (см. пример ниже).
Аналогично в нем можно указывать дополнительные требования за счет аннотаций, например: не парсить указанные поля, использовать кастомный конструктор класса, поменять имя переменной (например не firstName , а fName ) и многое другое. Подробнее см. в документации.
ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(jsonString, Person.class); System.out.println("My fio: " + person.firstName + " " + person.lastName + " and my friends are: "); for (Person friend : person.friends) < System.out.print(friend.lastName); for (Phones phone : friend.phoneNumbers) < System.out.println(" - phone type: " + phone.type + ", phone number : " + phone.number); >> // output: // My fio: Json Smith and my friends are: // Snow - phone type: home, phone number : 141 111-1234 // Tompson - phone type: home, phone number : 999 111-1234
JsonPath
Где взять: через Maven и другие сборщики / репозиторий на github
Относится к так называемым XPath библиотекам. Её суть аналогична xpath в xml, то есть легко получать часть информации из json‘а, по указанному пути. А также позволяет фильтровать по условию.
// Выведет все фамилии друзей List friendsLastnames = JsonPath.read(jsonString, "$.friends[*].lastName"); for (String lastname : friendsLastnames) < System.out.println(lastname); >// output: // Snow // Tompson
Пример с выборкой по условию:
// Поиск друга, которому больше 22 лет List friendsWithAges = JsonPath .using(Configuration.defaultConfiguration()) .parse(jsonString) .read("$.friends[?(@.age > 22)].lastName", List.class); for (String lastname : friendsWithAges) < System.out.println(lastname); >// output: // Tompson
Отслеживать
ответ дан 15 ноя 2017 в 13:35
Алексей Шиманский Алексей Шиманский
71.1k 12 12 золотых знаков 90 90 серебряных знаков 180 180 бронзовых знаков
У GSON также наличествует возможность менять поведение аннотациями
15 ноя 2017 в 14:08
Понимаю, зачем ТС задал такой вопрос и сам же на него и ответил, ибо действительно достали вопросы новичков как парсить Json. Предлагаю ответ сделать общим и на вопросы по Json далее ставить дубли со ссылкой на этот ответ.
15 ноя 2017 в 14:23
@Barmaley я бы предложил писать еще ответы, чтоб хотя бы ответ не был полотном гигантским. И еще хочу ЮрийСПб попросить чтоб отдельно написал ответы по Android, думаю там есть что-то тоже отдельно
15 ноя 2017 в 14:31
@rjhdby добавил сий нюанс в ответ.
15 ноя 2017 в 15:27
@Barmaley, для этого не надо ничего делать общим.
20 ноя 2017 в 18:56
Еще несколько вариантов
LoganSquare
LoganSquare — основана на Jackson‘s streaming API. По демонстрируемым тестам работает быстрее GSON и Jackson. Поэтому хорош для Android.
Где взять: репозиторий на github / или через Maven / Gradle и пр.
- Классы должны быть помечены аннотацией @JsonObject
- Поля должны быть помечены аннотацией @JsonField (с различными варианциями входных параметров, например @JsonField(name=»message») )
- Другие предъявляемые требования: https://github.com/bluelinelabs/LoganSquare/blob/development/docs/Models.md
@JsonObject public class Person < @JsonField(name="firstName") public String firstName; @JsonField(name="age") public int age; public void say() < System.out.println(); System.out.println("My name is " + firstName + " , I'm " + age + " years old!"); >>
String jsonString = ""; Person person = LoganSquare.parse(jsonString, Person.class); person.say(); // My name is Adam , I'm 18 years old!
Moshi
Moshi is a modern JSON library for Android and Java.
Хорош, как утверждают разработчики, для работы с Android.
Где взять: репозиторий на github / или через Maven / Gradle и пр.
-
Пример разбора Json строки в объект Person :
Moshi moshi = new Moshi.Builder().build(); JsonAdapter jsonAdapter = moshi.adapter(Person.class); Person person = jsonAdapter.fromJson(jsonStringPerson); // В person будут все данные
class Seanse < public String name; public String locate public String metro; public Listsessions; > class Sessions < public String time; public double price; >public class Main < public static void main(String[] args) throws IOException < String jsonStringForMap = "<\"2\":<\"sessions\":[<\"time\":\"13:00\",\"price\":\"410\">,< \"time\":\"06:40\",\"price\":\"340\">,< \"time\":\"16:50\",\"price\":\"370\">],\"name\":\"Кинокис-L\",\"locate\":\"Москва, Садовая-Спасская ул., 21, 56\",\"metro\":\"Красные ворота\">,\"7\":< \"sessions\":[ < \"time\":\"06:35\",\"price\":\"190\">,< \"time\":\"00:05\",\"price\":\"410\">],\"name\":\"Кинокис-V\",\"locate\":\"Павелецкая пл., 2, строение 1\",\"metro\":\"Павелецкая\">,\"8\":< \"sessions\":[ < \"time\":\"15:10\",\"price\":\"330\">],\"name\":\"Кинокис-J\",\"locate\":\"ул. Пречистенка, 40/2\",\"metro\":\"Кропоткинская\">,\"9\":< \"sessions\":[ < \"time\":\"13:00\",\"price\":\"600\">,< \"time\":\"08:30\",\"price\":\"300\">,< \"time\":\"04:00\",\"price\":\"510\">,< \"time\":\"13:15\",\"price\":\"340\">],\"name\":\"Кинокис-U\",\"locate\":\"Шарикоподшипниковская ул., 24\",\"metro\":\"Дубровка\">>"; Moshi moshi = new Moshi.Builder().build(); Type map = Types.newParameterizedType(Map.class, String.class, Seanse.class); JsonAdapter> jsonAdapter = moshi.adapter(map); Map seanseMap = jsonAdapter.fromJson(jsonStringForMap); > >
Genson
Где взять: здесь / репозиторий на github / или через Maven и пр.
За счет создания POJO (создаются классы, которые повторяют структуру Json‘а) — парсится объект из строки, распихивая по нужным полям объектов. Есть возможность фильтровать свойства, включить или исключить поля при парсинге, переименовать, возможность работы с аннотациями и пр. Подробнее в документации.
Genson genson = new Genson(); Person person = genson.deserialize(jsonString, Person.class); // В person будут все данные
List persons = genson.deserialize("[, ]", List.class); // persons - список с данными объектов
. JSON для разбора:
< "2":< "sessions":[ < "time":"13:00", "price":"410" >, < "time":"06:40", "price":"340" >, < "time":"16:50", "price":"370" >], "name":"Кинокис-L", "locate":"Москва, Садовая-Спасская ул., 21, 56", "metro":"Красные ворота" >, "7":< "sessions":[ < "time":"06:35", "price":"190" >, < "time":"00:05", "price":"410" >], "name":"Кинокис-V", "locate":"Павелецкая пл., 2, строение 1", "metro":"Павелецкая" >, "8": < "sessions":[ < "time":"15:10", "price":"330" >], "name":"Кинокис-J", "locate":"ул. Пречистенка, 40/2", "metro":"Кропоткинская" >, "9":< "sessions":[ < "time":"13:00", "price":"600" >, < "time":"08:30", "price":"300" >, < "time":"04:00", "price":"510" >, < "time":"13:15", "price":"340" >], "name":"Кинокис-U", "locate":"Шарикоподшипниковская ул., 24", "metro":"Дубровка" > >
class Seanse < public String name; public String locate public String metro; public Listsessions; > class Sessions
String jsonStringForMap = "ТУТ JSON СТРОКА, ОПИСАННАЯ ВЫШЕ"; Genson genson = new Genson(); Map seansesMap = genson.deserialize(jsonStringForMap, Map.class);
FastJson
Где взять: через Maven и другие сборщики / репозиторий на github. Непосредственно описание работы с xpath. Осторожно, ̶н̶е̶н̶о̶р̶м̶а̶т̶и̶в̶н̶а̶я̶ ̶л̶е̶к̶с̶и̶к̶а̶ китайский язык.
Относится к XPath аналогам.
Person person = JSON.parseObject(jsonString, Person.class); int age = person.age; System.out.println(age); // 30
// Выведет все фамилии друзей List friendsLastnames = (List) JSONPath.eval(person, "$.friends.lastName"); for (String lastname : friendsLastnames) < System.out.println(lastname); // Snow Tompson >// Поиск друга, которому больше 22 лет List friendsWithAges = (List) JSONPath.eval(person, "$.friends[?(@.age > 22)].lastName"); for (String lastname : friendsWithAges) < System.out.println(lastname); // Tompson >
Отслеживать
ответ дан 25 дек 2017 в 15:53
Алексей Шиманский Алексей Шиманский
71.1k 12 12 золотых знаков 90 90 серебряных знаков 180 180 бронзовых знаков
JSON-P
Поддерживает сериализацию и парсинг JSON без предварительного маппинга в классах:
Maven:
javax.json javax.json-api 1.1.2 org.glassfish javax.json 1.1.2
Пример разбора строки JSON:
public static void main(String[] args) throws IOException
Пример вывода объекта в строку JSON:
public static void main(String[] args) throws IOException < System.out.println(prettyPrintJson(jsonObject, 0)); >public static String prettyPrintJson(JsonObject jsonObject, int indent) < String indentStr = getIndentStr(indent); String prettyJson = indentStr + "prettyJson = prettyJson.substring(0, prettyJson.length() - 1); prettyJson += "\n" + indentStr + " ]"; > catch (Exception e) < try < prettyJson += "\n" + prettyPrintJson(jsonObject.get(key).asJsonObject(), indent + 2); >catch (Exception ee) < prettyJson += jsonObject.get(key).toString(); >> prettyJson += ","; > prettyJson = prettyJson.substring(0, prettyJson.length() - 1); prettyJson += "\n" + indentStr + ">"; return prettyJson; > public static String getIndentStr(int indent) < String indentStr = ""; for (int i = 0; i < indent; i++) < indentStr += " "; >return indentStr; >
< "firstName": "Json", "lastName": "Smith", "age": 30, "address": < "streetAddress": "666 1nd Street", "city": "New York", "state": "NY", "postalCode": 10021 >, "phoneNumbers": [ < "type": "home", "number": "542 666-1234" >, < "type": "fax", "number": "653 666-4567" >], "friends": [ < "firstName": "Test", "lastName": "Snow", "age": 20, "phoneNumbers": [ < "type": "home", "number": "141 111-1234" >], "friends": [ < "firstName": "UnknownFirstName", "lastName": "UnknownLastName", "age": 999, "phoneNumbers": [ < "type": "home", "number": "000 000-0000" >] > ] >, < "firstName": "Flash", "lastName": "Tompson", "age": 23, "phoneNumbers": [ < "type": "home", "number": "999 111-1234" >] > ] >
Отслеживать
ответ дан 30 ноя 2017 в 15:43
user236980 user236980
Поддерживает сериализацию и парсинг JSON без предварительного маппинга в классах — потому что это ручной разбор, при котором разработчику известна структура и нужно писать велосипеды аналогично похожему Simple Json %)
30 ноя 2017 в 16:15
Когда известна структура наверно можно посмотреть ещё один sjr specification номер 367 или json-b (json binding)
26 дек 2017 в 13:30
Здесь расположена общая информация о парсерах, которая может помочь при выборе и понять, что он умеет. Текст и таблица, представленные ниже, взяты из публикации на Habrahabr: Шпаргалка Java программиста 8. Библиотеки для работы с Json, автор статьи @ВеденинВячеслав
- Data bind
- Tree Model
- Streaming API
- Аналоги XPath (дополнительный способ)
Data bind
Самый популярный и простой способ — вы просто указываете класс, который нужно преобразовать в json, может быть часть полей отмечаете аннотациями (а зачастую даже это необязательно), а библиотека сама превращает этот класс и всю его иерархию классов в json.
Плюсы: наиболее простой из всех
Минусы: скорость и память. Большинство библиотек использует рефлексию и т.п. методы работы с Java классами (хотя не все), что очевидно не очень быстро. К тому же, весь json файл сразу превращается в Java объекты, что может просто исчерпать всю доступную память, если вы попытаетесь обработать очень большой json.
Вывод: если нет проблем с производительностью, памятью и вы не собираетесь обрабатывать многогигабайтные json’ы скорее всего самый лучший способ.
Tree Model
Данный парсер представляет json в виде Java классов таких как Node или `JsonElement c иерархической структурой, а уже сам программист их обходит и получает из них информацию.
Плюсы: обычно быстрее первого способа и проще третьего
Минусы: уступает Data bind по простоте, плюс ряд библиотек способен генерить классы при Data bind, а не использовать рефлексию, в этом случае то что Tree Model будет быстрее не очевидно, к тому же не решается проблема огромных файлов и ограничения памяти.
Streaming API
Самый низкоуровневый способ, по сути программист сам вручную разбирает токены json’a. Зато никаких ограничений по памяти и в теории максимальная производительность.
Плюсы: производительность и минимальное потребление памяти
Минусы: сложность использования
Аналоги XPath
Не очень подходит, если нужно получит всю информацию из json‘a, зато позволяет написав выражение, например $.store.book[*].author получить список всех авторов всех книг из json‘a магазина. То есть легко получать часть информации из json‘а.
Плюсы: позволяет быстро получить информацию из json‘а по сложным критериям
Минусы: не очень подходит, когда нужна все информация из json‘а, не работает в обратную сторону на формирования json‘ов
Таблица библиотек и способы парсинга, которые они поддерживают:
Способ\Hазвание Fastjson Gson LoganSquare JSONjava Moshi Jackson Genson JsonPath SimpleJson Data bind Да Да Да - Да Да Да - - Tree Model - Да - Да - Да - - Да Streaming API - Да - - - Да - - - Аналоги XPath Да - - - - - - Да - Генерация классов - - Да - - - - - для Data bind* Работает со Да Да Нет - Да Да Да - static inner class** Обязательность Нет Нет Да - Нет Нет Нет - аннотаций***
* — Генерация классов для Data bind позволяет сгенерировать классы на стадии компиляции, что в теории должно давать значительный прирост производительности библиотеки,
** — Работает со static inner class имеет смысл только для случая Data bind, возможно ли сериализация и десериализация для случая статических внутренних классов (не статические внутренние классы сериализовать не рекомендуется),
*** — тоже только для случая Data bind можно ли не использовать аннотации или их использование крайне рекомендуется,
JSON формат
В этом уроке мы с вами более подробно познакомимся с форматом JSON . А потом из этого формата получим наш User объект.
JSON стал общепринятым форматом для обмена данными в клиент-серверных приложения. Он является универсальным форматом для обмена данными.
Представьте, что вам нужно создать систему приложений, в которую входит, сервер, web -клиент, ios -клиент, android -клиент. У всех технологий разные языки,
разные особенности. Поэтому сервер отвечает в формате JSON , а клиенты на своей стороне приводят к нужному формату ответы. Подробнее про JSON формат можно
почитать здесь, но на данном этапе ваших знаний уже вполне хватит.
JSONObject, работа с JSON в java коде
Давайте создадим новый класс в пакете network и назовём его JsonParser для преобразования Json -строк в необходимые нам объекты. Добавим в него один
метод, который назовём getUser(String response) :
1 2 3 4 5 6 7 8 9 10
package colibri.dev.com.colibritweet.network; import colibri.dev.com.colibritweet.pojo.User; public class JsonParser public User getUser(String response) return null; > >
Мы будем использовать этот метод внутри класса HttpClient , передавая в него ответ от сервера в формате String , возвращая объект User . Давайте
разберём преобразование, рассмотрим структура хранения JSON . В прошлом уроке мы в конце вывели ответ от сервера в log и увидели очень большой объект JSON .
На данном этапе нам необходимы только те поля, которые мы отображаем на экране. Поэтому опустим остальные поля и оставим только те, которые нам нужны:
1 2 3 4 5 6 7 8 9 10
< "id": 929257819349700600, "name": "Devcolibri", "screen_name": "devcolibri", "location": "Republic of Belarus", "description": "Образовательный IT-портал. Android, Java, Kotlin.", "profile_image_url": "http://pbs.twimg.com/profile_images/929258919402377216/JDAtj1H__normal.jpg", "followers_count": 5, "favourites_count": 0, >
Видим, что наш JSON полностью повторяет структуру нашего объекта User . Теперь можно приступить к парсингу (преобразованию) данных.
Первое, что необходимо сделать – это создать JSON объект из строки:
1 2 3 4 5 6 7 8 9 10 11
package colibri.dev.com.colibritweet.network; import colibri.dev.com.colibritweet.pojo.User; public class JsonParser public User getUser(String response) JSONObject userJson = new JSONObject(response); return null; > >
Видим, что AndroidStudio подчёркивает эту строку, указывая что надо обработать исключение или добавить его к сигнатуре метода. Можем нажать alt + enter
и увидеть два этих варианта решения проблемы. Добавим исключение к сигнатуре, чтобы обработать исключения в клиентском коде. Для этого выберем вариант Add exception to method signature :
JSONObject представляет из себя структуру типа HashMap (ключ – значение).
Т.е. чтобы получить значения поля id нам необходимо выполнить вызов метода
userJson.getLong(«id») (получить значение типа long по ключу (названию поля) id ). Давайте сделаем тоже самое для каждого поля.
После этого метод будет выглядеть так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class JsonParser public User getUser(String response) throws JSONException JSONObject userJson = new JSONObject(response); long id = userJson.getLong("id"); String name = userJson.getString("name"); String nick = userJson.getString("screen_name"); String location = userJson.getString("location"); String description = userJson.getString("description"); String imageUrl = userJson.getString("profile_image_url"); int followersCount = userJson.getInt("followers_count"); int followingCount = userJson.getInt("favourites_count"); return null; > >
Т.е. вот так по названию поля мы можем достать его значение. Нам попался самый простой случай, где наши значения являются примитивными типами. На практике мы
поработаем с массивами элементов и вложенными объектами.
Давайте создадим объект User , передав ему в конструктор все поля, которые мы только что достали из userJson :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class JsonParser public User getUser(String response) throws JSONException JSONObject userJson = new JSONObject(response); long id = userJson.getLong("id"); String name = userJson.getString("name"); String nick = userJson.getString("screen_name"); String location = userJson.getString("location"); String description = userJson.getString("description"); String imageUrl = userJson.getString("profile_image_url"); int followersCount = userJson.getInt("followers_count"); int followingCount = userJson.getInt("favourites_count"); return new User(id, imageUrl, name, nick, description, location, followingCount, followersCount); > >
Вот и всё! Теперь давайте добавим использование нашего класса внутри класса HttpClient .
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 30 31 32 33 34 35 36 37
public class HttpClient private static final String HEADER_AUTHORIZATION = "Authorization"; private static final String GET = "GET"; private final JsonParser jsonParser; public HttpClient() jsonParser = new JsonParser(); > public User readUserInfo(long userId) throws IOException, JSONException String requestUrl = "https://api.twitter.com/1.1/users/show.json?user_id=" + userId; URL url = new URL(requestUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // add auth header to request String authHeader = getAuthHeader(requestUrl); connection.setRequestProperty(HEADER_AUTHORIZATION, authHeader); connection.connect(); InputStream in; int status = connection.getResponseCode(); if (status != HttpURLConnection.HTTP_OK) in = connection.getErrorStream(); > else in = connection.getInputStream(); > String response = convertStreamToString(in); User user = jsonParser.getUser(response); return user; > // остальной код ниже не изменился >
Добавили JsonParser как final поле в классе HttpClient и инициализируем его в конструкторе.
После этого добавили строку User user = jsonParser.getUser(response); в конец метода getUserInfo и поменяли возвращаемый тип на User и добавили новое
исключение JSONException в сигнатуру метода. Отлично, теперь изменим код в UserInfoActivity и запустим приложение.
в UserInfoActivity нам нужно изменить метод loadUserInfo :
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
public class UserInfoActivity extends AppCompatActivity // остальной код выше не изменился @SuppressLint("StaticFieldLeak") private void loadUserInfo(final Long userId) new AsyncTaskVoid, Void, User>() @Override protected User doInBackground(Void. voids) try return httpClient.readUserInfo(userId); > catch (IOException | JSONException e) e.printStackTrace(); return null; > > @Override protected void onPostExecute(User user) displayUserInfo(user); > >.execute(); > // остальной код ниже не изменился >
- Возвращаемый тип Asynctask со String на User .
- Добавили в catch блок перехват исключения типа IOException | JSONException .
- В onPostExecute мы заменили вызов Log.d() на вызов реального метода отображения displayUserInfo(user) .
Давайте запустим наше приложение:
Всё работает! Только видим, что наш ник выводится без символа @ . Давайте изменим метод getNick() в классе User . Будем добавлять в него символ @ самостоятельно, т.к. сервер этого не сделал.
1 2 3 4 5 6 7 8 9 10
public class User // Остальной код выше не изменился public String getNick() return "@" + nick; > // Остальной код ниже не изменился >
Запустим наше приложение и увидим, что теперь с форматом поля nick всё в порядке:
Полный листинг кода:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
package colibri.dev.com.colibritweet.network; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import com.twitter.sdk.android.core.TwitterAuthConfig; import com.twitter.sdk.android.core.TwitterCore; import com.twitter.sdk.android.core.TwitterSession; import com.twitter.sdk.android.core.internal.oauth.OAuth1aHeaders; import org.json.JSONException; import colibri.dev.com.colibritweet.pojo.User; public class HttpClient private static final String HEADER_AUTHORIZATION = "Authorization"; private static final String GET = "GET"; private final JsonParser jsonParser; public HttpClient() jsonParser = new JsonParser(); > public User readUserInfo(long userId) throws IOException, JSONException String requestUrl = "https://api.twitter.com/1.1/users/show.json?user_id=" + userId; URL url = new URL(requestUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // add auth header to request String authHeader = getAuthHeader(requestUrl); connection.setRequestProperty(HEADER_AUTHORIZATION, authHeader); connection.connect(); InputStream in; int status = connection.getResponseCode(); if (status != HttpURLConnection.HTTP_OK) in = connection.getErrorStream(); > else in = connection.getInputStream(); > String response = convertStreamToString(in); User user = jsonParser.getUser(response); return user; > private String convertStreamToString(InputStream stream) throws IOException BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) sb.append(line).append("\n"); > stream.close(); return sb.toString(); > private String getAuthHeader(String url) TwitterAuthConfig authConfig = TwitterCore.getInstance().getAuthConfig(); TwitterSession session = TwitterCore.getInstance().getSessionManager().getActiveSession(); return new OAuth1aHeaders().getAuthorizationHeader(authConfig, session.getAuthToken(), null, GET, url, null); > >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
package colibri.dev.com.colibritweet.network; import org.json.JSONException; import org.json.JSONObject; import colibri.dev.com.colibritweet.pojo.User; public class JsonParser public User getUser(String response) throws JSONException JSONObject userJson = new JSONObject(response); long id = userJson.getLong("id"); String name = userJson.getString("name"); String nick = userJson.getString("screen_name"); String location = userJson.getString("location"); String description = userJson.getString("description"); String imageUrl = userJson.getString("profile_image_url"); int followersCount = userJson.getInt("followers_count"); int followingCount = userJson.getInt("favourites_count"); return new User(id, imageUrl, name, nick, description, location, followingCount, followersCount); > >
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
package colibri.dev.com.colibritweet.activity; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import android.annotation.SuppressLint; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; import org.json.JSONException; import colibri.dev.com.colibritweet.R; import colibri.dev.com.colibritweet.adapter.TweetAdapter; import colibri.dev.com.colibritweet.network.HttpClient; import colibri.dev.com.colibritweet.pojo.Tweet; import colibri.dev.com.colibritweet.pojo.User; public class UserInfoActivity extends AppCompatActivity private ImageView userImageView; private TextView nameTextView; private TextView nickTextView; private TextView descriptionTextView; private TextView locationTextView; private TextView followingCountTextView; private TextView followersCountTextView; private RecyclerView tweetsRecyclerView; private TweetAdapter tweetAdapter; private Toolbar toolbar; private HttpClient httpClient; @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_info); long userId = getIntent().getLongExtra(AuthActivity.USER_ID, -1); userImageView = findViewById(R.id.user_image_view); nameTextView = findViewById(R.id.user_name_text_view); nickTextView = findViewById(R.id.user_nick_text_view); descriptionTextView = findViewById(R.id.user_description_text_view); locationTextView = findViewById(R.id.user_location_text_view); followingCountTextView = findViewById(R.id.following_count_text_view); followersCountTextView = findViewById(R.id.followers_count_text_view); toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); initRecyclerView(); httpClient = new HttpClient(); loadUserInfo(userId); loadTweets(); > @Override public boolean onCreateOptionsMenu(Menu menu) getMenuInflater().inflate(R.menu.user_info_menu, menu); return true; > @Override public boolean onOptionsItemSelected(MenuItem item) if(item.getItemId() == R.id.action_search) Intent intent = new Intent(this, SearchUsersActivity.class); startActivity(intent); > return true; > private void loadTweets() CollectionTweet> tweets = getTweets(); tweetAdapter.setItems(tweets); > private CollectionTweet> getTweets() return Arrays.asList( new Tweet(getUser(), 1L, "Thu Dec 13 07:31:08 +0000 2017", "Очень длинное описание твита 1", 4L, 4L, "https://www.w3schools.com/w3css/img_fjords.jpg"), new Tweet(getUser(), 2L, "Thu Dec 12 07:31:08 +0000 2017", "Очень длинное описание твита 2", 5L, 5L, "https://www.w3schools.com/w3images/lights.jpg"), new Tweet(getUser(), 3L, "Thu Dec 11 07:31:08 +0000 2017", "Очень длинное описание твита 3", 6L, 6L, "https://www.w3schools.com/css/img_mountains.jpg") ); > private void initRecyclerView() tweetsRecyclerView = findViewById(R.id.tweets_recycler_view); tweetsRecyclerView.setLayoutManager(new LinearLayoutManager(this)); tweetAdapter = new TweetAdapter(); tweetsRecyclerView.setAdapter(tweetAdapter); > @SuppressLint("StaticFieldLeak") private void loadUserInfo(final Long userId) new AsyncTaskVoid, Void, User>() @Override protected User doInBackground(Void. voids) try return httpClient.readUserInfo(userId); > catch (IOException | JSONException e) e.printStackTrace(); return null; > > @Override protected void onPostExecute(User user) displayUserInfo(user); > >.execute(); > private void displayUserInfo(User user) Picasso.with(this).load(user.getImageUrl()).into(userImageView); nameTextView.setText(user.getName()); nickTextView.setText(user.getNick()); descriptionTextView.setText(user.getDescription()); locationTextView.setText(user.getLocation()); String followingCount = String.valueOf(user.getFollowingCount()); followingCountTextView.setText(followingCount); String followersCount = String.valueOf(user.getFollowersCount()); followersCountTextView.setText(followersCount); getSupportActionBar().setTitle(user.getName()); > private User getUser() return new User( 1L, "http://i.imgur.com/DvpvklR.png", "DevColibri", "devcolibri", "Sample description", "USA", 42, 42 ); > >
Поздравляем, вы только что закончили полный цикл работы с сервером. Давайте подведём итоги:
- Формат JSON широко используется для обмена данными между клиентом и сервером
- Этот формат не привязан ни к какой технологии, поэтому он так широко используется
- Структура данных представляет из себя ключ — значение , что позволяет удобно работать с ним
- В Android есть класс JSONObject , который позволяет парсить JSON в любой необходимый формат данных
- Русскоязычные:
- Что такое JSON
- Официальная документация. JSONObject
Кофе-брейк #175. Как мы можем прочитать файл JSON в Java? Что такое Java Development Kit (JDK)?
Источник: DZone JSON — это простой формат для хранения и отправки данных на веб-страницу. Обычно он используется в JavaScript, но сегодня мы узнаем, как с ним работать в Java.
Чтение файла JSON в Java
- JSON — это текстовый файл, поэтому его можно легко передавать.
- JSON не зависит от конкретного языка.
Синтаксис
Данные в файле JSON должны быть в формате пар имя/значение, запятыми разделяют различные данные. Фигурные скобки используются для хранения объектов, а квадратные скобки — для хранения массивов.
Особенности JSON
- Простой.
- Имеет независимую платформу.
- Легко передать.
- Поддерживает расширяемость.
- Наличие совместимости.
Типы данных
- String — строка представлена внутри кавычек.
- Number — представляет числовые символы.
- Boolean – состоит либо из true, либо из false.
- Null – пустой.
JSON в Java
- JSON-объекты;
- JSON-массивы.
JSON-объекты
JSON-объекты представлены между фигурными скобками. Объекты должны быть в парах ключ/значение (key/value). Ключ представлен в виде String, а значения представляют любые типы данных, упомянутые выше. Пример:
Key, value pairs -
JSON-массивы
Массивы JSON используются для хранения объектов. Эти объекты заключены в квадратные скобки []. Пример:
В приведенном выше примере сведения о студентах представлены в виде массива, а внутри массива данные о студентах хранятся в виде объектов.
Простая программа для JSON на Java
import org.json.simple.JSONObject; public class Json < public static void main(String args[]) < JSONObject j = new JSONObject(); j.put("Name", "Kotte"); j.put("College", "BVRIT"); j.put("Branch" , "Computer science engineering"); j.put("Section", "CSE-C"); System.out.println(j); >>
Чтение файла JSON в Java
Чтобы прочитать файл JSON в Java, необходимо использовать метод FileReader(). Пример:
Приведенный выше код — это файл, который используется для чтения. Мы используем библиотеку json.simple .
//program for reading a JSON file import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.*; public class JSON < public static void main(Strings args[]) < // file name is File.json Object o = new JSONParser().parse(new FileReader(File.json)); JSONObject j = (JSONObject) o; String Name = (String) j.get("Name"); String College = (String ) j.get("College"); System.out.println("Name :" + Name); System.out.println("College :" +College); >>
Name: Kotte College: BVRIT
В данной программе используется JSONParser().parse() , который присутствует в org.json.simple.parser.* для анализа файла File.json.
Что такое Java Development Kit (JDK)?
Источник: Medium Эта публикация ознакомит вас с работой и сферой использования Java Development Kit. В своей работе программисты часто используют Java Development Kit (Комплект для разработки Java), известный как JDK. Он представляет собой кроссплатформенный набор инструментов и библиотек для создания программных приложений и апплетов на основе Java. Пакет JDK включает в себя как виртуальную машину Java (известную как JVM), так и среду выполнения Java (известную как JRE). Также в JDK имеется компилятор javac, инструменты мониторинга производительности, отладчик, стандартные библиотеки классов Java, примеры, документация и различные утилиты. Разработкой Java Development Kit (JDK) занимается корпорация Oracle. В ее продукте реализованы JVMS, JLS и Java API SE (API). Помимо коммерческой версии Oracle представила на рынке бесплатную версию пакета OpenJDK. Также на рынке Java-разработки существуют альтернативные JDK от других компаний. Если единственное, что вы хотите сделать на своем компьютере, — это запускать Java-приложения, то вам не нужно беспокоиться о различиях между Java Runtime Environment (JRE) и Java Development Kit (JDK). Однако вам понадобится Java Development Kit (JDK) для создания программного обеспечения на основе Java. Среда выполнения Java (JRE), входящая в состав JDK, называется частной средой выполнения (Private Runtime). Эта среда отличается от стандартной JRE тем, что включает дополнительные компоненты. Также она дает разработчикам доступ к виртуальной машине Java (JVM) и всем библиотекам классов, используемым в производственных средах, в дополнение к библиотекам интернационализации и IDL.
Самые популярные JDK
- Azul Systems Zing : высокопроизводительная виртуальная машина Java с малой задержкой для Linux.
- Azul Systems (для Linux, Windows, Mac OS X и IBM J9 JDK: для AIX, Linux, Windows и многих других операционных систем).
- Amazon Corretto (OpenJDK и долгосрочная поддержка включены).
Скомпилируйте и запустите код Java с помощью JDK
Вы можете создать исполняемую программу Java из текстового файла с помощью компилятора JDK. При компиляции ваш Java-код преобразуется в байт-код с расширением .class . Для начала вам нужно создать текстовый файл Java и сохранить его под уникальным именем. В данном случае мы сохраняем Hello.java в качестве имени файла. Затем запустите инструмент компиляции Java командой javac , и все готово. Чтобы избежать получения сообщения об ошибке, такого как “The system cannot locate a path supplied” (Система не может найти указанный путь), вы должны указать полный путь к вашему текстовому файлу Java. Hello — это имя файла, а полному пути к файлу предшествует Hello в следующем примере команды. Путь и исполняемый файл для javac.exe должны быть заключены в кавычки. Теперь, когда Hello.class создан, вы можете увидеть его в том же каталоге, что и Hello.java , что очень удобно. Теперь вы можете выполнить свой код, просто набрав java hello в своем терминале. Имейте в виду, что запуск вашего кода не требуется включение файла .class.
Компонент Jar
В JDK включены многие важные инструменты. Помимо javac чаще всего используется инструмент jar. В нем можно найти не что иное, как набор классов Java. Как только файлы .class будут готовы, вы можете упаковать их и сохранить в архиве, известном как “jar”. После этого jar-файл можно запускать в мобильной среде (Android).