1. Обзор
В этой статье мы рассмотрим потоковый API Джексона. Он поддерживает как чтение, так и запись, и с его помощью мы можем писать высокопроизводительные и быстрые парсеры JSON.
С другой стороны, это немного сложно использовать-каждая деталь данных JSON должна обрабатываться явно в коде.
2. Зависимость Maven
Во-первых, нам нужно добавить зависимость Maven в jackson-core :
com.fasterxml.jackson.core jackson-core 2.11.1
3. Запись в JSON
Мы можем записать содержимое JSON непосредственно в OutputStream с помощью класса JsonGenerator |. Во-первых, нам нужно создать экземпляр этого объекта:
ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonFactory jfactory = new JsonFactory(); JsonGenerator jGenerator = jfactory .createGenerator(stream, JsonEncoding.UTF8);
Далее предположим, что мы хотим написать JSON со следующей структурой:
{ "name":"Tom", "age":25, "address":[ "Poland", "5th avenue" ] }
Мы можем использовать экземпляр JsonGenerator для записи определенных полей непосредственно в OutputStream:
jGenerator.writeStartObject(); jGenerator.writeStringField("name", "Tom"); jGenerator.writeNumberField("age", 25); jGenerator.writeFieldName("address"); jGenerator.writeStartArray(); jGenerator.writeString("Poland"); jGenerator.writeString("5th avenue"); jGenerator.writeEndArray(); jGenerator.writeEndObject(); jGenerator.close();
Чтобы проверить, был ли создан правильный JSON, мы можем создать объект String с объектом JSON в нем:
String json = new String(stream.toByteArray(), "UTF-8"); assertEquals( json, "{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}");
4. Разбор JSON
Когда мы получаем JSON String в качестве входных данных и хотим извлечь из него определенные поля, можно использовать класс Json Parser :
String json = "{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}"; JsonFactory jfactory = new JsonFactory(); JsonParser jParser = jfactory.createParser(json); String parsedName = null; Integer parsedAge = null; Listaddresses = new LinkedList<>();
Мы хотим получить parsedName, parsedAge и адреса полей из входного JSON. Чтобы достичь этого, нам нужно обработать логику низкоуровневого синтаксического анализа и реализовать ее самостоятельно:
while (jParser.nextToken() != JsonToken.END_OBJECT) { String fieldname = jParser.getCurrentName(); if ("name".equals(fieldname)) { jParser.nextToken(); parsedName = jParser.getText(); } if ("age".equals(fieldname)) { jParser.nextToken(); parsedAge = jParser.getIntValue(); } if ("address".equals(fieldname)) { jParser.nextToken(); while (jParser.nextToken() != JsonToken.END_ARRAY) { addresses.add(jParser.getText()); } } } jParser.close();
В зависимости от имени поля мы извлекаем его и назначаем соответствующему полю. После анализа документа все поля должны содержать правильные данные:
assertEquals(parsedName, "Tom"); assertEquals(parsedAge, (Integer) 25); assertEquals(addresses, Arrays.asList("Poland", "5th avenue"));
5. Извлечение частей JSON
Иногда, когда мы анализируем документ JSON, нас интересует только одно конкретное поле.
В идеале в таких ситуациях мы хотим проанализировать только начало документа, и как только нужное поле будет найдено, мы можем прервать обработку.
Допустим, нас интересует только поле age входного JSON. В этом случае мы можем реализовать логику синтаксического анализа, чтобы остановить синтаксический анализ, как только будет найдено нужное поле:
while (jParser.nextToken() != JsonToken.END_OBJECT) { String fieldname = jParser.getCurrentName(); if ("age".equals(fieldname)) { jParser.nextToken(); parsedAge = jParser.getIntValue(); return; } } jParser.close();
После обработки единственное поле parsed Age будет иметь значение:
assertNull(parsedName); assertEquals(parsedAge, (Integer) 25); assertTrue(addresses.isEmpty());
Благодаря этому разбор документа JSON будет намного быстрее, потому что нам не нужно читать весь документ, а только небольшую его часть.
6. Заключение
В этой краткой статье мы рассмотрим, как мы можем использовать API обработки потоков из Джексона.
Реализацию всех этих примеров и фрагментов кода можно найти на GitHub – это проект Maven, поэтому его должно быть легко импортировать и запускать как есть.