Перейти к основному содержимому

Джексон распаковывает JSON с неизвестными свойствами

· 3 мин. чтения

1. Обзор

В этом руководстве мы рассмотрим процесс десортировки с помощью Jackson 2.x, в частности, как работать с содержимым JSON с неизвестными свойствами .

Чтобы копнуть глубже и узнать о других интересных вещах, которые мы можем делать с Джексоном, мы можем просмотреть основной учебник по Джексону .

2. Распаковать JSON с дополнительными/неизвестными полями

Входные данные JSON бывают разных форм и размеров, и в большинстве случаев нам нужно сопоставить их с предопределенными объектами Java с заданным количеством полей. Цель состоит в том, чтобы просто игнорировать любые свойства JSON, которые не могут быть сопоставлены с существующим полем Java .

Например, предположим, что нам нужно преобразовать JSON в следующий объект Java:

public class MyDto {

private String stringValue;
private int intValue;
private boolean booleanValue;

// standard constructor, getters and setters
}

2.1. UnrecognizedPropertyException для неизвестных полей

Попытка демаршалировать JSON с неизвестными свойствами в эту простую Java-сущность приведет к com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException :

@Test(expected = UnrecognizedPropertyException.class)
public void givenJsonHasUnknownValues_whenDeserializing_thenException()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
"{"stringValue":"a"," +
""intValue":1," +
""booleanValue":true," +
""stringValue2":"something"}";
ObjectMapper mapper = new ObjectMapper();

MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);

assertNotNull(readValue);
}

Это не удастся со следующим исключением:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: 
Unrecognized field "stringValue2" (class org.foreach.jackson.ignore.MyDto),
not marked as ignorable (3 known properties: "stringValue", "booleanValue", "intValue"])

2.2. Работа с неизвестными полями с помощью ObjectMapper

Теперь мы можем настроить полный ObjectMapper для игнорирования неизвестных свойств в JSON:

new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Затем мы должны иметь возможность читать этот вид JSON в предопределенный объект Java:

@Test
public void givenJsonHasUnknownValuesButJacksonIsIgnoringUnknowns_whenDeserializing_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {

String jsonAsString =
"{"stringValue":"a"," +
""intValue":1," +
""booleanValue":true," +
""stringValue2":"something"}";
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);

assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo("a"));
assertThat(readValue.isBooleanValue(), equalTo(true));
assertThat(readValue.getIntValue(), equalTo(1));
}

2.3. Работа с неизвестными полями на уровне класса

Мы также можем пометить один класс как принимающий неизвестные поля вместо всего Jackson ObjectMapper :

@JsonIgnoreProperties(ignoreUnknown = true)
public class MyDtoIgnoreUnknown { ... }

Теперь мы должны иметь возможность протестировать то же поведение, что и раньше. Неизвестные поля просто игнорируются, и сопоставляются только известные поля:

@Test
public void givenJsonHasUnknownValuesButIgnoredOnClass_whenDeserializing_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {

String jsonAsString =
"{"stringValue":"a"," +
""intValue":1," +
""booleanValue":true," +
""stringValue2":"something"}";
ObjectMapper mapper = new ObjectMapper();

MyDtoIgnoreUnknown readValue = mapper
.readValue(jsonAsString, MyDtoIgnoreUnknown.class);

assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo("a"));
assertThat(readValue.isBooleanValue(), equalTo(true));
assertThat(readValue.getIntValue(), equalTo(1));
}

3. Распаковать неполный JSON

Подобно дополнительным неизвестным полям, распаковка неполного JSON, JSON, который не содержит всех полей в классе Java, не является проблемой для Джексона:

@Test
public void givenNotAllFieldsHaveValuesInJson_whenDeserializingAJsonToAClass_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString = "{"stringValue":"a","booleanValue":true}";
ObjectMapper mapper = new ObjectMapper();

MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);

assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo("a"));
assertThat(readValue.isBooleanValue(), equalTo(true));
}

4. Вывод

В этой статье мы обсудили десериализацию JSON с дополнительными неизвестными свойствами с помощью Jackson.

Это одна из наиболее распространенных вещей, которую нужно настроить при работе с Джексоном, поскольку нам часто нужно сопоставлять результаты JSON внешних API REST с внутренним Java-представлением сущностей API.

Реализацию всех этих примеров и фрагментов кода можно найти в моем проекте на GitHub .