Здравствуйте!
Часто возникает потребность работы с 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"
}
]
}
]
}
Достать данные можно разными способами и, конечно, зависит от задач. Попробую рассмотреть основные.
Заметка: для каждого из примеров для парсинга будет взят 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()) {
JSONObject test = (JSONObject) phonesItr.next();
System.out.println("- type: " + test.get("type") + ", phone: " + test.get("number"));
}
Остальная работа с вложенными массивами аналогична. Можно складывать в List, Map и пр.
Где взять: здесь / репозиторий на github / или через Maven и пр.
Документация: http://www.studytrails.com/java/json/java-google-json-introduction/
Позволяет парсить Json также, как и Json-simple, т.е. используя JSONObject
и JSONArray
(см. документацию), но имеет более мощный инструмент парсинга.
Достаточно создать классы, которые повторяют структуру Json'а. Для парсинга Json из вопроса создадим классы:
class Person {
public String firstName;
public String lastName;
public int age;
public Address address;
public ArrayList<Phones> phoneNumbers;
public ArrayList<Person> friends;
}
class Address {
public String streetAddress;
public String city;
public String state;
public int postalCode;
}
class Phones {
public String type;
public String number;
}
Теперь достаточно написать:
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
Дополнительно можно использовать аннотации, например: исключить указанные поля при парсинге, поменять имя переменной (например не personFirstName
, а fName
) и многое другое. Подробнее см. в документации.
Где взять: здесь / репозиторий на github / или через Maven и пр.
Документация и примеры: https://github.com/FasterXML/jackson-docs
Как и 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
Где взять: через Maven и другие сборщики / репозиторий на github
Относится к так называемым XPath библиотекам. Её суть аналогична xpath в xml, то есть легко получать часть информации из json'а, по указанному пути. А также позволяет фильтровать по условию.
// Выведет все фамилии друзей
List<String> friendsLastnames = JsonPath.read(jsonString, "$.friends[*].lastName");
for (String lastname : friendsLastnames) {
System.out.println(lastname);
}
// output:
// Snow
// Tompson
Пример с выборкой по условию:
// Поиск друга, которому больше 22 лет
List<String> friendsWithAges = JsonPath
.using(Configuration.defaultConfiguration())
.parse(jsonString)
.read("$.friends[?(@.age > 22)].lastName", List.class);
for (String lastname : friendsWithAges) {
System.out.println(lastname);
}
// output:
// Tompson
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Пытаюсь изменить ориентацию на recyclerview во время выполнения по событию onScrolledНиже привожу метод onCreate():
Имеется 3 textField, в которые нужно вводить только целые или дробные числаПо нажатию кнопки произвожу вычисления с числами, вытянутыми из textField'ов,...
Вопрос такой: Нужно сделать так, чтобы int раз в 5 секунд меняла своё значение(В начале 0, через 5 секунд - 1, 1 на одну секунду, потом опять 0 и так...
Здравствуйте! В общем пытаюсь настроить VS Code для компиляции java-файловУстановил расширения: