Jackson ist eine beliebte Bibliothek zum Serialisieren/Deserialisieren von Java-Objekten in verschiedene Textformate. Die ObjectMapper- Klasse ist die wichtigste Möglichkeit der Bibliothek, mit dem JSON-Format zu arbeiten. Für andere Formate haben wir dessen Nachkommen ( XmlMapper , YAMLMapper ). Dank der Vererbung können wir über eine einzige Schnittstelle mit allen Formaten konsistent arbeiten.

Laden Sie JAR-Dateien herunter

Bevor wir die Beispiele studieren, müssen wir Jackson-JAR-Dateien herunterladen und sie mit dem Projekt in IntelliJ IDEA verbinden. Nehmen wir das Beispiel von jackson-databind, um zu sehen, wie nach benötigten Dateien gesucht wird:

  1. Gehen Sie zur Maven Repository- Website.

  2. Geben Sie „ jackson-databind “ in das Suchfeld ein. Sie erhalten Folgendes:

  3. Das erste Suchergebnis ist das, was uns interessiert. Folgen Sie dem Link.

  4. Manchmal ist möglicherweise eine bestimmte Version einer Bibliothek erforderlich, um die Kompatibilität mit anderen Komponenten in einem Projekt sicherzustellen. Die neueste Version sollte funktionieren (zum Zeitpunkt des Schreibens dieser Lektion ist es 2.13.2.2). Folge dem Link.

  5. Auf der Seite, die sich öffnet, möchten Sie den Link „Bundle“:

  6. Laden Sie die JAR-Datei über diesen Link herunter .

Nach einem ähnlichen Verfahren können Sie die restlichen erforderlichen JAR-Dateien finden und herunterladen:

Nachdem Sie alle erforderlichen Dateien heruntergeladen haben, verbinden Sie sie mit dem Projekt in IntelliJ IDEA:

  1. Öffnen Sie die Projekteinstellungen (Sie können dies mit der Tastenkombination Strg+Alt+Umschalt+S tun).

  2. Gehen Sie zu Bibliotheken .

  3. Drücken Sie + und dann „Java“. Wählen Sie alle heruntergeladenen Dateien aus. Folgendes sollten wir am Ende haben:

  4. Damit sind unsere Vorarbeiten abgeschlossen. Jetzt können wir ObjectMapper in Aktion ausprobieren .

Serialisierung nach JSON

Lassen Sie uns zunächst ein Objekt in JSON serialisieren:


import com.fasterxml.jackson.databind.ObjectMapper;
 
class Book {
	public String title;
	public String author;
	public int pages;
}
 
public class Solution {
	public static void main(String[] args) throws Exception {
    	Book book = new Book();
    	book.title = "Good Omens";
    	book.author = "Pratchett T., Gaiman N.";
    	book.pages = 383;
 
    	ObjectMapper mapper = new ObjectMapper();
    	String jsonBook = mapper.writeValueAsString(book);
    	System.out.println(jsonBook);
	}
}

Wenn Sie main ausführen, erhalten Sie diese Ausgabe:

{"title":Gute Omen,Autor:Pratchett T., Gaiman N.,Seiten:383}

Der ObjectMapper verfügt über viele erweiterte Einstellungen. Lassen Sie uns eine davon verwenden, um die JSON-Zeichenfolge besser lesbar zu machen. Nach dem Erstellen desObjectMapperObjekt, führen Sie diese Anweisung aus:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Die Informationen in der Ausgabe bleiben gleich, nur gibt es nun Einrückungen und Zeilenumbrüche:

{
  „title“ : „Good Omens“,
  „author“ : „Pratchett T., Gaiman N.“,
 „pages“ : 383
}

Deserialisierung von JSON

Führen wir nun den umgekehrten Vorgang aus: Wir deserialisieren einen String in ein Objekt. Um zu sehen, was das Programm tut, überschreiben wir die toString- Methode in der Book- Klasse:


@Override
public String toString() {
	return "Book{" +
        	"title='" + title + '\'' +
        	", author='" + author + '\'' +
        	", pages=" + pages +
        	'}';
}

Und wir werden in der Hauptmethode Folgendes tun :


public static void main(String[] args) throws Exception {
	String jsonString = "{\"title\":\"Good Omens\",\"author\":\"Pratchett T., Gaiman N.\",\"pages\":383}";
	Book book = new ObjectMapper().readValue(jsonString, Book.class);
	System.out.println(book);
}

Ausgang:

Buch{Titel='Good Omens', Autor='Pratchett T., Gaiman N.', Seiten=383}

Die readValue- Methode ist überladen – es gibt viele Variationen, die eine Datei, einen Link, verschiedene Eingabestreams usw. akzeptieren. Der Einfachheit halber verwendet unser Beispiel eine Variante, die eine JSON-Zeichenfolge akzeptiert.

Wie oben erwähnt, verfügt ObjectMapper über viele Einstellungen. Schauen wir uns einige davon an.

Unbekannte Eigenschaften ignorieren

Stellen Sie sich eine Situation vor, in der eine JSON-Zeichenfolge eine Eigenschaft hat, die in der Book- Klasse nicht vorhanden ist :


public static void main(String[] args) throws Exception {
	String jsonString = """
        	{
          	"title" : "Good Omens",
          	"author" : "Pratchett T., Gaiman N.",
          	"pages" : 383,
          	"unknown property" : 42
        	}""";
	ObjectMapper mapper = new ObjectMapper();
	Book book = mapper.readValue(jsonString, Book.class);
	System.out.println(book);
}

Das Ausführen dieses Codes führt zu einer UnrecognizedPropertyException . Dies ist das Standardverhalten, aber wir können es ändern:


ObjectMapper mapper =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Beim Erstellen einesObjectMapper-Objekt verwenden wir die Methode configure , um die entsprechende Einstellung auf false zu setzen . Die Methode configure ändert das Objekt, für das sie aufgerufen wurde, und gibt dann dasselbe Objekt zurück, sodass wir diesen Aufruf auf andere Weise durchführen können:


ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Von der Funktionalität her entspricht diese Notation der vorherigen.

Wenn wir nun die Hauptmethode ausführen , gelingt die Deserialisierung und die unbekannte Eigenschaft wird ignoriert.

Praktische Anmerkungen

Jackson stellt uns mehrere Anmerkungen zur Verfügung, die es uns ermöglichen, den Serialisierungsprozess auf vielfältige Weise anzupassen. Werfen wir einen Blick auf einige der nützlichsten:

@JsonIgnore – Diese Annotation wird über einem Element platziert, das während der Serialisierung/Deserialisierung ignoriert werden soll:


class Book {
	public String title;
	@JsonIgnore
	public String author;
	public int pages;
}

Hier dasAutorDas Feld wird während der Serialisierung nicht in den resultierenden JSON aufgenommen. Bei der Deserialisierung wird dieAutorDas Feld erhält den Standardwert (null), auch wenn der JSON-Wert einen anderen Wert hatte.

@JsonFormat – Mit dieser Annotation können Sie das Format der serialisierten Daten festlegen. Fügen wir der Book- Klasse ein weiteres Feld hinzu, ein Date :


class Book {
	public String title;
	public String author;
	public int pages;
	public Date createdDate = new Date();
}

Nach der Serialisierung erhalten wir den folgenden JSON:

 {
  „title“ : „Good Omens“,
  „author“ : „Pratchett T., Gaiman N.“,
  „pages“ : 383,
  „createdDate“ : 1649330880788
}

Wie Sie sehen, wurde das Datum als Zahl serialisiert. Wir fügen eine Anmerkung hinzu und legen das Format fest:


class Book {
	public String title;
	public String author;
	public int pages;
	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
	public Date createdDate = new Date();
}

Das Ergebnis der Serialisierung ist nun:

{
  „title“ : „Good Omens“,
  „author“ : „Pratchett T., Gaiman N.“,
  „pages“ : 383,
  „createdDate“ : „2022-04-07“
}

@JsonProperty – Mit dieser Annotation können Sie den Namen der Eigenschaft ändern, die das serialisierte Feld darstellt. Sie können mit dieser Annotation auch Methoden markieren. Wenn Sie dies tun, wird ihr Rückgabewert während der Serialisierung in eine JSON-Eigenschaft umgewandelt:


class Book {
	@JsonProperty("name")
	public String title;
	public String author;
	public int pages;
 
	@JsonProperty("quotedTitle")
	public String getQuotedTitle() {
    	    return "\"" + title + "\"";
	}
}

Ergebnis der Seralisierung:

{
  „author“ : „Pratchett T., Gaiman N.“,
  „pages“ : 383,
  „name“ : „Good Omens“,
  „quotedTitle“ : „\“Good Omens\““
}

@JsonInclude – Mit dieser Annotation können Sie Bedingungen angeben, die erfüllt sein müssen, damit ein Feld serialisiert wird. Sie können es auf einzelne Felder oder eine ganze Klasse anwenden. Versuchen wir zunächst, ein Objekt mit nicht initialisierten Feldern zu serialisieren:


public class Solution {
	public static void main(String[] args) throws Exception {
    		Book book = new Book();

    		ObjectMapper mapper = new ObjectMapper();
    		mapper.enable(SerializationFeature.INDENT_OUTPUT);
    		String jsonBook = mapper.writeValueAsString(book);
    		System.out.println(jsonBook);
	}
}

Ergebnis der Seralisierung:

{
  „title“ : null,
  „author“ : null,
  „pages“ : 0
}

Und wenn Sie die Anmerkung hinzufügen:


@JsonInclude(JsonInclude.Include.NON_NULL)
class Book {
	public String title;
	public String author;
	public int pages;
}

Dann erhalten wir dieses Ergebnis:

{
  "Seiten" : 0
}

Jetzt werden Felder, die null sind , nicht serialisiert.

@JsonPropertyOrder – Mit dieser Annotation können Sie die Reihenfolge festlegen, in der Felder serialisiert werden:


@JsonPropertyOrder({"author", "title", "pages"})
class Book {
	public String title;
	public String author;
	public int pages;
}

Ergebnis der Seralisierung:

{
  „author“ : „Pratchett T., Gaiman N.“,
  „title“ : „Good Omens“,
  „pages“ : 383
}

Denken Sie zunächst nur daran, wie Sie Anmerkungen verwenden. Am Ende dieses Moduls werden wir sie besser kennenlernen und sogar eigene Anmerkungen erstellen.

Serialisierung und Deserialisierung in XML

Wenn wir in XML serialisieren müssen, können wir dieselben Einstellungen und Anmerkungen verwenden. Der einzige Unterschied besteht in der Implementierung desMapper-Objekt:


public static void main(String[] args) throws Exception {
	Book book = new Book();
	book.title = "Good Omens";
	book.author = "Pratchett T., Gaiman N.";
	book.pages = 383;
 
	ObjectMapper mapper = new XmlMapper();
	mapper.enable(SerializationFeature.INDENT_OUTPUT);
	String xmlBook = mapper.writeValueAsString(book);
	System.out.println(xmlBook);
}

Ausgang:

 <Book>
  <title>Good Omens</title>
  <author>Pratchett T., Gaiman N.</author>
  <pages>383</pages>
</Book>

Deserialisierung von XML:


public static void main(String[] args) throws Exception {
   String xmlString = """
            <Book>
             <title>Good Omens</title>
             <author>Pratchett T., Gaiman N.</author>
             <pages>383</pages>
           </Book>""";
   ObjectMapper mapper = new XmlMapper();
   Book book = mapper.readValue(xmlString, Book.class);
   System.out.println(book);
}

Serialisierung und Deserialisierung in YAML

Wir gehen mit YAML genauso um wie mit XML:


public static void main(String[] args) throws Exception {
	Book book = new Book();
	book.title = "Good Omens";
	book.author = "Pratchett T., Gaiman N.";
	book.pages = 383;
 
	ObjectMapper mapper = new YAMLMapper();
	mapper.enable(SerializationFeature.INDENT_OUTPUT);
	String yamlBook = mapper.writeValueAsString(book);
	System.out.println(yamlBook);
}

Ausgang:

---
Titel: „Good Omens“
Autor: „Pratchett T., Gaiman N.“
Seiten: 383

Deserialisierung von YAML:


public static void main(String[] args) throws Exception {
   String yamlString = """
           ---
           title: "Good Omens"
           author: "Pratchett T., Gaiman N."
           pages: 383""";
   ObjectMapper mapper = new YAMLMapper();
   Book book = mapper.readValue(yamlString, Book.class);
   System.out.println(book);
}