1 . Обзор
В этой статье мы рассмотрим API потоковой передачи Jackson. Он поддерживает как чтение, так и запись, и с его помощью мы можем писать высокопроизводительные и быстрые парсеры JSON.
С другой стороны, его немного сложно использовать — каждую деталь данных JSON необходимо явно обрабатывать в коде.
2. Зависимость от Maven
Во- первых, нам нужно добавить зависимость Maven к jackson-core
:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.1</version>
</dependency>
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 в качестве входных данных и хотим извлечь из нее определенные поля, можно использовать класс JsonParser :
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;
List<String> addresses = new LinkedList<>();
Мы хотим получить поля parsedName, parsedAge и address
из входного 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();
После обработки единственное поле parsedAge
будет иметь значение:
assertNull(parsedName);
assertEquals(parsedAge, (Integer) 25);
assertTrue(addresses.isEmpty());
Благодаря этому синтаксический анализ документа JSON будет намного быстрее, потому что нам не нужно читать весь документ, а только его небольшую часть.
6. Заключение
В этой быстрой статье мы рассмотрим, как мы можем использовать API Stream Processing от Jackson.
Реализацию всех этих примеров и фрагментов кода можно найти на GitHub — это проект Maven, поэтому его должно быть легко импортировать и запускать как есть.