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

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

1. обзор

В этой статье мы собираемся взглянуть на процесс демаршаллинга с помощью Jackson 2.x, в частности наhow to deal with JSON content with unknown properties.

Если вы хотите копнуть глубже и узнать о других интересных вещах, которые вы можете сделать с Джексоном, переходите кthe main Jackson tutorial.

2. Неупорядочить JSON с дополнительными / неизвестными полями

Входные данные JSON бывают всех форм и размеров - и в большинстве случаев нам необходимо сопоставить их с предопределенными объектами Java с заданным количеством полей. Цель состоит в том, чтобы простоignore any JSON properties that cannot be mapped to an existing Java field.

Например, скажем, нам нужно демонтировать 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.example.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. Работа с неизвестными полями в классе

We can also mark a single class as accepting unknown fields вместо всего Джексона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.

Это одна из самых распространенных вещей, которые нужно настраивать при работе с Джексоном, поскольку часто нам нужноmap JSON results of external REST APIs to an internal Java representationсущностей API.

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