Jackson er et populært bibliotek for serialisering/deserialisering av Java-objekter til forskjellige tekstformater. ObjectMapper - klassen er bibliotekets viktigste måte å jobbe med JSON-formatet på. For andre formater har vi dens etterkommere ( XmlMapper , YAMLMapper ). Takket være arv kan vi jobbe med alle formater på en konsistent måte, gjennom ett enkelt grensesnitt.

Last ned jar-filer

Før vi studerer eksemplene, må vi laste ned Jackson jar-filer og koble dem til prosjektet i IntelliJ IDEA. La oss ta eksemplet med jackson-databind for å se hvordan du søker etter nødvendige filer:

  1. Gå til nettstedet til Maven Repository .

  2. Skriv inn " jackson-databind " i søkefeltet. Du får følgende:

  3. Det første søkeresultatet er det vi er interessert i. Følg lenken.

  4. Noen ganger kan det være nødvendig med en bestemt versjon av et bibliotek for å sikre kompatibilitet med andre komponenter i et prosjekt. Den nyeste versjonen skal fungere (på tidspunktet for skriving av denne leksjonen er den 2.13.2.2). Følg linken.

  5. På siden som åpnes vil du ha koblingen "bunt":

  6. Last ned jar-filen ved å bruke denne lenken .

Ved å følge en lignende prosedyre kan du finne og laste ned resten av de nødvendige jar-filene:

Etter å ha lastet ned alle nødvendige filer, koble dem til prosjektet i IntelliJ IDEA:

  1. Åpne prosjektinnstillingene (du kan gjøre med Ctrl+Alt+Shift+S- tastekombinasjonen).

  2. Gå til biblioteker .

  3. Trykk på + og deretter "Java". Velg alle nedlastede filer. Her er hva vi bør ende opp med:

  4. Det avslutter vårt forarbeid. Nå kan vi prøve ut ObjectMapper i aksjon.

Serialisering til JSON

Først, la oss serialisere noe 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);
	}
}

Kjører main vil gi deg denne utgangen:

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

ObjectMapper har mange avanserte innstillinger . La oss bruke en av dem for å gjøre JSON-strengen mer lesbar. Etter å ha opprettetObjectMapperobjekt, utfør denne setningen:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Informasjonen i utgangen forblir den samme, men nå er det innrykk og linjeskift:

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

Deserialisering fra JSON

La oss nå gjøre den motsatte handlingen: vi deserialiserer en streng til et objekt. For å kunne se hva programmet gjør, la oss overstyre toString -metoden i Book- klassen:


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

Og vi vil gjø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);
}

Produksjon:

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

ReadValue - metoden er overbelastet — den har mange varianter som tar en fil, en lenke, ulike input-strømmer osv. For enkelhets skyld bruker eksemplet vårt en variant som aksepterer en JSON-streng.

Som nevnt ovenfor har ObjectMapper mange innstillinger. La oss se på noen av dem.

Ignorerer ukjente egenskaper

Tenk på en situasjon der en JSON-streng har en egenskap som ikke eksisterer i Book- klassen:


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

Å kjøre denne koden gir oss et UnrecognizedPropertyException . Dette er standardoppførselen, men vi kan endre den:


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

Når du oppretter enObjectMapperobjekt, bruker vi konfigureringsmetoden for å sette den tilsvarende innstillingen til false . Konfigurasjonsmetoden endrer objektet det ble kalt på og returnerer deretter det samme objektet, slik at vi kan gjøre dette anropet på en annen måte :


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

Når det gjelder funksjonalitet, er denne notasjonen akkurat som den forrige.

Hvis vi nå kjører hovedmetoden , vil deserialiseringen lykkes og den ukjente egenskapen vil bli ignorert.

Praktiske merknader

Jackson gir oss flere merknader som lar oss tilpasse serialiseringsprosessen på alle mulige måter. La oss ta en titt på noen av de mest nyttige:

@JsonIgnore — Denne merknaden er plassert over et element som bør ignoreres under serialisering/deserialisering:


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

Her erforfatterfeltet vil ikke inkluderes i den resulterende JSON under serialisering. Ved deserialisering vilforfattervil få standardverdien (null), selv om JSON hadde en annen verdi.

@JsonFormat — Denne merknaden lar deg angi formatet for de serialiserte dataene. La oss legge til ett felt til, en dato , til bokklassen :


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

Etter serialisering får vi følgende JSON:

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

Som du kan se, ble datoen serialisert som et tall. Vi legger til en merknad og angir 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();
}

Nå er resultatet av serialisering:

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

@JsonProperty — Denne merknaden lar deg endre navnet på egenskapen som representerer det serialiserte feltet. Du kan også merke metoder med denne merknaden. Hvis du gjør det, vil returverdien deres konverteres til en JSON-egenskap under serialisering:


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

Resultat av seralisering:

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

@JsonInclude — Ved å bruke denne merknaden kan du spesifisere betingelser som må være oppfylt for at et felt skal serialiseres. Du kan bruke det på individuelle felt eller en hel klasse. Først, la oss prøve å serialisere et objekt med uinitialiserte felt:


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 av seralisering:

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

Og hvis du legger til kommentaren:


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

Da får vi dette resultatet:

{
  "sider" : 0
}

Nå serialiseres ikke felt som er null .

@JsonPropertyOrder — Denne merknaden lar deg angi rekkefølgen feltene skal serialiseres i:


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

Resultat av seralisering:

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

For nå, bare husk hvordan du bruker merknader. På slutten av denne modulen vil vi bli bedre kjent med dem og til og med lage våre egne merknader.

Serialisering og deserialisering i XML

Hvis vi trenger å serialisere til XML, kan vi bruke alle de samme innstillingene og merknadene. Den eneste forskjellen vil være implementeringen avkartleggerobjekt:


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

Produksjon:

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

Deserialisering av 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åte 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);
}

Produksjon:

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

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