Jackson Unmarshalling von JSON mit unbekannten Eigenschaften

Jackson entfernt JSON mit unbekannten Eigenschaften

1. Überblick

In diesem Artikel werden wir uns den Unmarshalling-Prozess mit Jackson 2.x ansehen - speziell beihow to deal with JSON content with unknown properties.

Wenn Sie tiefer graben und andere coole Dinge lernen möchten, die Sie mit dem Jackson tun können, gehen Sie zuthe main Jackson tutorial.

2. Unmarshall ein JSON mit zusätzlichen / unbekannten Feldern

JSON-Eingaben sind in allen Formen und Größen verfügbar. In den meisten Fällen müssen sie vordefinierten Java-Objekten mit einer festgelegten Anzahl von Feldern zugeordnet werden. Das Ziel ist einfachignore any JSON properties that cannot be mapped to an existing Java field.

Angenommen, wir müssen JSON für die folgende Java-Entität dekomprimieren:

public class MyDto {

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

    // standard constructor, getters and setters
}

2.1. UnrecognizedPropertyException in unbekannten Feldern

Der Versuch, einen JSON mit unbekannten Eigenschaften für diese einfache Java-Entität zu entfernen, führt zu einemcom.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);
}

Dies schlägt mit der folgenden Ausnahme fehl:

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. Umgang mit unbekannten Feldern aufObjectMapper

Wir können jetzt die vollständigenObjectMapper so konfigurieren, dass unbekannte Eigenschaften im JSON ignoriert werden:

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

Wir sollten dann in der Lage sein, diese Art von JSON in eine vordefinierte Java-Entität einzulesen:

@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. Umgang mit unbekannten Feldern in der Klasse

We can also mark a single class as accepting unknown fields anstelle der gesamten JacksonObjectMapper:

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

Jetzt sollten wir das gleiche Verhalten wie zuvor testen können - unbekannte Felder werden einfach ignoriert und nur bekannte Felder werden zugeordnet:

@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. Unmarshall ein unvollständiger JSON

Ähnlich wie bei weiteren unbekannten Feldern ist das Aufheben der Bereitstellung eines unvollständigen JSON - eines JSON, der nicht alle Felder in der Java-Klasse enthält - bei Jackson kein Problem:

@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. Fazit

In diesem Artikel wurde die Deserialisierung eines JSON mit zusätzlichen, unbekannten Eigenschaften unter Verwendung von Jackson behandelt.

Dies ist eine der häufigsten Konfigurationen bei der Arbeit mit Jackson, da häufigmap JSON results of external REST APIs to an internal Java representation der Entitäten der API benötigt werden.

Die Implementierung all dieser Beispiele und Codefragmente finden Sie inmy GitHub project.