Einführung in den Jackson ObjectMapper

Einführung in den Jackson ObjectMapper

1. Überblick

Diese Beschreibung konzentriert sich auf das Verständnis der JacksonObjectMapper-Klasse - und darauf, wie Java-Objekte in JSON serialisiert und JSON-Zeichenfolgen in Java-Objekte deserialisiert werden. Um mehr über die Jackson-Bibliothek im Allgemeinen zu erfahren, istJackson Tutorial ein guter Anfang.

Weitere Lektüre:

Vererbung mit Jackson

In diesem Lernprogramm wird gezeigt, wie die Einbeziehung von Subtyp-Metadaten und das Ignorieren von Eigenschaften, die von Superklassen mit Jackson geerbt wurden, gehandhabt werden.

Read more

Jackson JSON Ansichten

Verwendung der @ JsonView-Annotation in Jackson zur perfekten Steuerung der Serialisierung Ihrer Objekte (ohne und mit Spring).

Read more

Jackson - Benutzerdefinierter Serializer

Steuern Sie Ihre JSON-Ausgabe mit Jackson 2 mithilfe eines benutzerdefinierten Serializers.

Read more

2. Abhängigkeiten

Fügen wir zunächst die folgenden Abhängigkeiten zupom.xmlhinzu:


    com.fasterxml.jackson.core
    jackson-databind
    2.9.8

Durch diese Abhängigkeit werden auch die folgenden Bibliotheken transitiv zum Klassenpfad hinzugefügt:

  1. jackson-annotations-2.9.8.jar

  2. jackson-core-2.9.8.jar

  3. jackson-databind-2.9.8.jar

Verwenden Sie fürJackson databind immer die neuesten Versionen im zentralen Maven-Repository.

3. Lesen und Schreiben mitObjectMapper

Beginnen wir mit den grundlegenden Lese- und Schreibvorgängen.

The simple readValue API of the ObjectMapper is a good entry point. Wir können es verwenden, um JSON-Inhalte in ein Java-Objekt zu analysieren oder zu deserialisieren.

Auch auf der Schreibseite der Dingewe can use the writeValue API to serialize any Java object as JSON output.

Wir verwenden die folgendeCar-Klasse mit zwei Feldern als Objekt zum Serialisieren oder Deserialisieren in diesem Artikel:

public class Car {

    private String color;
    private String type;

    // standard getters setters
}

3.1. Java-Objekt zu JSON

Sehen wir uns ein erstes Beispiel für die Serialisierung eines Java-Objekts in JSON mit der MethodewriteValueder KlasseObjectMapperan:

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
objectMapper.writeValue(new File("target/car.json"), car);

Die Ausgabe des Obigen in der Datei lautet:

{"color":"yellow","type":"renault"}

Die MethodenwriteValueAsString undwriteValueAsBytes der KlasseObjectMapper generieren einen JSON aus einem Java-Objekt und geben den generierten JSON als String oder als Byte-Array zurück:

String carAsString = objectMapper.writeValueAsString(car);

3.2. JSON nach Java Objekt

Im Folgenden finden Sie ein einfaches Beispiel für die Konvertierung eines JSON-Strings in ein Java-Objekt mithilfe der KlasseObjectMapper:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Car car = objectMapper.readValue(json, Car.class);

Die FunktionreadValue()akzeptiert auch andere Eingabeformen wie eine Datei mit einer JSON-Zeichenfolge:

Car car = objectMapper.readValue(new File("src/test/resources/json_car.json"), Car.class);

oder eine URL:

Car car = objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);

3.3. JSON an JacksonJsonNode

Alternativ kann ein JSON in einJsonNode-Objekt analysiert und zum Abrufen von Daten von einem bestimmten Knoten verwendet werden:

String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
// Output: color -> Black

3.4. Erstellen einer Java-Liste aus einer JSON-Array-Zeichenfolge

Wir können einen JSON in Form eines Arrays mitTypeReference: in eine Java-Objektliste analysieren

String jsonCarArray =
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>(){});

3.5. Erstellen einer Java Map aus einer JSON-Zeichenfolge

Ebenso können wir einen JSON in JavaMap analysieren:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map map
  = objectMapper.readValue(json, new TypeReference>(){});

4. Erweiterte Funktionen

Eine der größten Stärken der Jackson-Bibliothek ist der hochgradig anpassbare Serialisierungs- und Deserialisierungsprozess.

In diesem Abschnitt werden einige erweiterte Funktionen beschrieben, bei denen sich die Eingabe- oder Ausgabe-JSON-Antwort von dem Objekt unterscheiden kann, das die Antwort generiert oder verwendet.

4.1. Konfigurieren der Serialisierungs- oder Deserialisierungsfunktion

Wenn die JSON-Zeichenfolge beim Konvertieren von JSON-Objekten in Java-Klassen einige neue Felder enthält, führt der Standardprozess zu einer Ausnahme:

String jsonString
  = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";

Die JSON-Zeichenfolge im obigen Beispiel im Standard-Analyseprozess für das Java-Objekt fürClass Carführt zur AusnahmeUnrecognizedPropertyException.

Mit der Methodeconfigurekönnen wir den Standardprozess erweitern, um die neuen Felder zu ignorieren:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonString, Car.class);

JsonNode jsonNodeRoot = objectMapper.readTree(jsonString);
JsonNode jsonNodeYear = jsonNodeRoot.get("year");
String year = jsonNodeYear.asText();

Eine weitere Option basiert aufFAIL_ON_NULL_FOR_PRIMITIVES, die definiert, ob dienull-Werte für primitive Werte zulässig sind:

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

In ähnlicher Weise steuertFAIL_ON_NUMBERS_FOR_ENUM, ob Aufzählungswerte als Zahlen serialisiert / deserialisiert werden dürfen:

objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

Die umfassende Liste der Serialisierungs- und Deserialisierungsfunktionen finden Sie unterofficial site.

4.2. Erstellen eines benutzerdefinierten Serializers oder Deserializers

Ein weiteres wesentliches Merkmal der KlasseObjectMapper ist die Möglichkeit, benutzerdefinierteserializer unddeserializer zu registrieren. Benutzerdefinierter Serializer und Deserializer sind in Situationen sehr nützlich, in denen die Eingabe- oder Ausgabe-JSON-Antwort eine andere Struktur aufweist als die Java-Klasse, in die sie serialisiert oder deserialisiert werden muss.

Unten finden Sie ein Beispiel für einen benutzerdefinierten JSON-Serializer:

public class CustomCarSerializer extends StdSerializer {

    public CustomCarSerializer() {
        this(null);
    }

    public CustomCarSerializer(Class t) {
        super(t);
    }

    @Override
    public void serialize(
      Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("car_brand", car.getType());
        jsonGenerator.writeEndObject();
    }
}

Dieser benutzerdefinierte Serializer kann folgendermaßen aufgerufen werden:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
  new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "renault");
String carJson = mapper.writeValueAsString(car);

So sieht dasCar (als JSON-Ausgabe) auf der Clientseite aus:

var carJson = {"car_brand":"renault"}

Und hier ist ein Beispiel füra custom JSON deserializer:

public class CustomCarDeserializer extends StdDeserializer {

    public CustomCarDeserializer() {
        this(null);
    }

    public CustomCarDeserializer(Class vc) {
        super(vc);
    }

    @Override
    public Car deserialize(JsonParser parser, DeserializationContext deserializer) {
        Car car = new Car();
        ObjectCodec codec = parser.getCodec();
        JsonNode node = codec.readTree(parser);

        // try catch block
        JsonNode colorNode = node.get("color");
        String color = colorNode.asText();
        car.setColor(color);
        return car;
    }
}

Dieser benutzerdefinierte Deserializer kann folgendermaßen aufgerufen werden:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
  new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
module.addDeserializer(Car.class, new CustomCarDeserializer());
mapper.registerModule(module);
Car car = mapper.readValue(json, Car.class);

4.3. Umgang mit Datumsformaten

Die Standardserialisierung vonjava.util.Date erzeugt eine Zahl, d.h. Zeitstempel der Epoche (Anzahl der Millisekunden seit dem 1. Januar 1970, UTC). Dies ist jedoch nicht sehr gut lesbar und erfordert eine weitere Konvertierung in ein für Menschen lesbares Format.

Schließen wir die bisher verwendeteCar-Instanz in dieRequest-Klasse mit derdatePurchased-Eigenschaft ein:

public class Request
{
    private Car car;
    private Date datePurchased;

    // standard getters setters
}

So steuern Sie das Zeichenfolgenformat eines Datums und stellen es auf z. yyyy-MM-dd HH:mm a z, betrachten Sie das folgende Snippet:

ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);
String carAsString = objectMapper.writeValueAsString(request);
// output: {"car":{"color":"yellow","type":"renault"},"datePurchased":"2016-07-03 11:43 AM CEST"}

Um mehr über das Serialisieren von Daten mit Jackson zu erfahren, lesen Sieour more in-depth write-up.

4.4. Umgang mit Sammlungen

Eine weitere kleine, aber nützliche Funktion, die über dieDeserializationFeature-Klasse verfügbar ist, ist die Möglichkeit, aus einer JSON-Array-Antwort den gewünschten Auflistungstyp zu generieren.

Zum Beispiel können wir das Ergebnis als Array erzeugen:

String jsonCarArray =
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);
// print cars

Oder alsList:

String jsonCarArray =
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>(){});
// print cars

Weitere Informationen zum Umgang mit Sammlungen mit Jackson finden Sie unterhere.

5. Fazit

Jackson ist eine solide und ausgereifte JSON-Serialisierungs- / Deserialisierungsbibliothek für Java. DieObjectMapper-API bietet eine einfache Möglichkeit, JSON-Antwortobjekte mit viel Flexibilität zu analysieren und zu generieren.

Der Artikel beschreibt die Hauptfunktionen, die die Bibliothek so beliebt machen. Der dem Artikel beiliegende Quellcode befindet sich inover on GitHub.