Jackson er et populært bibliotek til at serialisere/deserialisere Java-objekter til forskellige tekstformater. ObjectMapper - klassen er bibliotekets vigtigste måde at arbejde med JSON-formatet på. For andre formater har vi dens efterkommere ( XmlMapper , YAMLMapper ). Takket være arv, kan vi arbejde med alle formater på en ensartet måde gennem en enkelt grænseflade.

Download jar-filer

Før vi studerer eksemplerne, skal vi downloade Jackson jar-filer og forbinde dem til projektet i IntelliJ IDEA. Lad os tage eksemplet med jackson-databind for at se, hvordan man søger efter nødvendige filer:

  1. Gå til Maven Repository -webstedet.

  2. Indtast " jackson-databind " i søgefeltet. Du får følgende:

  3. Det første søgeresultat er det, vi er interesserede i. Følg linket.

  4. Nogle gange kan en bestemt version af et bibliotek være påkrævet for at sikre kompatibilitet med andre komponenter i et projekt. Den seneste version burde virke (på tidspunktet for denne lektion er den 2.13.2.2). Følg linket.

  5. På den side, der åbner, vil du have linket "bundt":

  6. Download jar-filen ved hjælp af dette link .

Ved at følge en lignende procedure kan du finde og downloade resten af ​​de nødvendige jar-filer:

Når du har downloadet alle de nødvendige filer, skal du forbinde dem til projektet i IntelliJ IDEA:

  1. Åbn projektindstillingerne (du kan gøre det med tastekombinationen Ctrl+Alt+Shift+S ).

  2. Gå til biblioteker .

  3. Tryk på + og derefter "Java". Vælg alle de downloadede filer. Her er hvad vi skal ende med:

  4. Det afslutter vores forberedende arbejde. Nu kan vi prøve ObjectMapper i aktion.

Serialisering til JSON

Lad os først serialisere noget objekt til JSON:


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);
	}
}

Hvis du kører main, får du dette output:

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

ObjectMapper har en masse avancerede indstillinger . Lad os bruge en af ​​dem til at gøre JSON-strengen mere læsbar. Efter at have oprettetObjectMapperobjekt, udfør denne sætning:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Informationen i output forbliver den samme, men nu er der indrykning og linjeskift:

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

Deserialisering fra JSON

Lad os nu gøre den modsatte handling: vi deserialiserer en streng til et objekt. For at kunne se, hvad programmet gør, lad os tilsidesætte toString -metoden i klassen Book :


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

Og vi vil gøre følgende i hovedmetoden :


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);
}

Produktion:

Bog{title='Good Omens', author='Pratchett T., Gaiman N.', pages=383}

ReadValue - metoden er overbelastet — den har mange variationer, der tager en fil, et link, forskellige inputstrømme osv. For nemheds skyld bruger vores eksempel en variant, der accepterer en JSON-streng.

Som nævnt ovenfor har ObjectMapper mange indstillinger. Lad os se på et par af dem.

Ignorerer ukendte egenskaber

Overvej en situation, hvor en JSON-streng har en egenskab, der ikke findes i klassen Book :


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);
}

Udførelse af denne kode giver os en UnrecognizedPropertyException . Dette er standardadfærden, men vi kan ændre den:


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

Når du opretter enObjectMapperobjekt, bruger vi konfigurationsmetoden til at indstille den tilsvarende indstilling til false . Konfigurationsmetoden ændrer det objekt, det blev kaldt på, og returnerer derefter det samme objekt, så vi kan foretage dette kald på en anden måde :


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

Med hensyn til funktionalitet er denne notation ligesom den forrige.

Hvis vi nu kører hovedmetoden , vil deserialiseringen lykkes, og den ukendte egenskab vil blive ignoreret.

Praktiske anmærkninger

Jackson giver os adskillige annotationer, der giver os mulighed for at tilpasse serialiseringsprocessen på alle mulige måder. Lad os tage et kig på nogle af de mest nyttige:

@JsonIgnore — Denne annotation er placeret over et element, der bør ignoreres under serialisering/deserialisering:


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

Her erforfatterfeltet vil ikke blive inkluderet i den resulterende JSON under serialisering. Ved deserialiseringenforfatterfeltet får standardværdien (null), selvom JSON havde en anden værdi.

@JsonFormat — Denne annotation lader dig indstille formatet for de serialiserede data. Lad os tilføje endnu et felt, en dato , til bogklassen :


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

Efter serialisering får vi følgende JSON:

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

Som du kan se, blev datoen serialiseret som et tal. Vi tilføjer en anmærkning og indstiller formatet:


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();
}

Nu er resultatet af serialisering:

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

@JsonProperty — Denne annotation lader dig ændre navnet på den egenskab, der repræsenterer det serialiserede felt. Du kan også markere metoder med denne annotering. Hvis du gør det, vil deres returværdi blive konverteret til en JSON-egenskab under serialisering:


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

Resultat af seralisering:

{
  "author" : "Pratchett T., Gaiman N.",
  "pages" : 383,
  "name" : "Gode varsler",
  "quotedTitle" : "\"Gode varsler\""
}

@JsonInclude — Ved at bruge denne annotation kan du angive betingelser, der skal være opfyldt, for at et felt kan serialiseres. Du kan anvende det på individuelle felter eller en hel klasse. Lad os først prøve at serialisere et objekt med ikke-initialiserede felter:


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);
	}
}

Resultat af seralisering:

{
  "title" : null,
  "author" : null,
  "pages" : 0
}

Og hvis du tilføjer anmærkningen:


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

Så får vi dette resultat:

{
  "sider" : 0
}

Nu serialiseres felter, der er null, ikke.

@JsonPropertyOrder — Denne annotation lader dig indstille rækkefølgen, hvori felter serialiseres:


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

Resultat af seralisering:

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

For nu skal du bare huske, hvordan du bruger annoteringer. I slutningen af ​​dette modul lærer vi dem bedre at kende og laver endda vores egne anmærkninger.

Serialisering og deserialisering i XML

Hvis vi skal serialisere til XML, kan vi bruge alle de samme indstillinger og anmærkninger. Den eneste forskel vil være implementeringen afmapper 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);
}

Produktion:

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

Deserialisering af 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);
}

Serialisering og deserialisering i YAML

Vi håndterer YAML på samme måde, som vi håndterer 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);
}

Produktion:

---
titel: "Good Omens"
forfatter: "Pratchett T., Gaiman N."
sider: 383

Deserialisering af 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);
}