Часто возникает потребность работы с 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. Заметка: для каждого из примеров для парсинга будет взят 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 и пр.
GSON Где взять: здесь / репозиторий на 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 List phoneNumbers public List 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
...... Классы (POJO): class Seanse { public String name public String locate public String metro public List sessions } class Sessions { public String time public double price } ...... Сам разбор выглядит так: Gson g = new Gson() Type type = new TypeToken>(){}.getType() Map myMap = g.fromJson(json, type) Всё. Дополнительно в GSON можно использовать аннотации, например: исключить указанные поля при парсинге, поменять имя переменной (например не personFirstName, а fName) и многое другое. Подробнее см. в документации.
Jackson Где взять: здесь / репозиторий на 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
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