Jackson este o bibliotecă populară pentru serializarea/deserializarea obiectelor Java în diferite formate de text. Clasa ObjectMapper este modalitatea principală a bibliotecii de a lucra cu formatul JSON. Pentru alte formate, avem descendenții săi ( XmlMapper , YAMLMapper ). Datorită moștenirii, putem lucra cu toate formatele într-un mod consistent, printr-o singură interfață.

Descărcați fișiere jar

Înainte de a studia exemplele, trebuie să descarcăm fișierele Jackson jar și să le conectăm la proiectul din IntelliJ IDEA. Să luăm exemplul jackson-databind pentru a vedea cum să căutați fișierele necesare:

  1. Accesați site-ul Maven Repository .

  2. Introduceți „ jackson-databind ” în caseta de căutare. Veți obține următoarele:

  3. Primul rezultat al căutării este ceea ce ne interesează. Urmați linkul.

  4. Uneori poate fi necesară o anumită versiune a unei biblioteci pentru a asigura compatibilitatea cu alte componente dintr-un proiect. Cea mai recentă versiune ar trebui să funcționeze (la momentul scrierii acestei lecții, este 2.13.2.2). Urmați linkul.

  5. Pe pagina care se deschide, doriți linkul „pachet”:

  6. Descărcați fișierul jar folosind acest link .

Urmând o procedură similară, puteți găsi și descărca restul fișierelor jar necesare:

După descărcarea tuturor fișierelor necesare, conectați-le la proiect în IntelliJ IDEA:

  1. Deschideți setările proiectului (puteți face cu combinația de taste Ctrl+Alt+Shift+S ).

  2. Accesați Biblioteci .

  3. Apăsați + și apoi „Java”. Selectați toate fișierele descărcate. Iată cu ce ar trebui să ajungem:

  4. Asta încheie munca noastră pregătitoare. Acum putem încerca ObjectMapper în acțiune.

Serializare la JSON

Mai întâi, să serializăm un obiect în 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);
	}
}

Rularea principală vă va oferi această ieșire:

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

ObjectMapper are o mulțime de setări avansate . Să folosim unul dintre ele pentru a face șirul JSON mai lizibil. După creareaObjectMapperobiect, executați această instrucțiune:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Informațiile din ieșire rămân aceleași, dar acum există indentări și întreruperi de linie:

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

Deserializare din JSON

Acum să facem acțiunea opusă: vom deserializa un șir într-un obiect. Pentru a putea vedea ce face programul, să înlocuim metoda toString din clasa Book :


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

Și vom face următoarele în metoda principală :


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

Ieșire:

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

Metoda readValue este supraîncărcată — are multe variante care iau un fișier, un link, diverse fluxuri de intrare etc. Pentru simplitate, exemplul nostru folosește o variantă care acceptă un șir JSON.

După cum am menționat mai sus, ObjectMapper are multe setări. Să ne uităm la câteva dintre ele.

Ignorarea proprietăților necunoscute

Luați în considerare o situație în care un șir JSON are o proprietate care nu există în clasa 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);
}

Executarea acestui cod ne dă o excepție UnrecognizedPropertyException . Acesta este comportamentul implicit, dar îl putem schimba:


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

La crearea unuiObjectMapperobiect, folosim metoda de configurare pentru a seta setarea corespunzătoare la false . Metoda configure modifică obiectul pe care a fost apelat și apoi returnează același obiect, astfel încât să putem face acest apel într-un mod diferit:


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

În ceea ce privește funcționalitatea, această notație este la fel ca cea anterioară.

Dacă rulăm acum metoda principală , deserializarea va reuși și proprietatea necunoscută va fi ignorată.

Adnotări convenabile

Jackson ne oferă mai multe adnotări care ne permit să personalizăm procesul de serializare în tot felul de moduri. Să aruncăm o privire la unele dintre cele mai utile:

@JsonIgnore — Această adnotare este plasată deasupra unui element care ar trebui ignorat în timpul serializării/deserializării:


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

Aiciautorcâmpul nu va fi inclus în JSON rezultat în timpul serializării. La deserializare,autorcâmpul va primi valoarea implicită (null), chiar dacă JSON a avut o valoare diferită.

@JsonFormat — Această adnotare vă permite să setați formatul datelor serializate. Să mai adăugăm un câmp, o dată , la clasa Book :


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

După serializare, obținem următorul JSON:

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

După cum puteți vedea, data a fost serializată ca număr. Vom adăuga o adnotare și vom seta formatul:


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

Acum rezultatul serializării este:

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

@JsonProperty — Această adnotare vă permite să schimbați numele proprietății care reprezintă câmpul serializat. De asemenea, puteți marca metodele cu această adnotare. Dacă o faceți, atunci valoarea lor returnată va fi convertită într-o proprietate JSON în timpul serializării:


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

Rezultatul serializării:

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

@JsonInclude — Folosind această adnotare, puteți specifica condițiile care trebuie îndeplinite pentru ca un câmp să fie serializat. Îl puteți aplica la câmpuri individuale sau la o clasă întreagă. Mai întâi, să încercăm să serializam un obiect cu câmpuri neinițializate:


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

Rezultatul serializării:

{
  „titlu”: nul,
  „autor”: nul,
  „pagini”: 0
}

Și dacă adăugați adnotarea:


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

Apoi obținem acest rezultat:

{
  "pagini" : 0
}

Acum câmpurile care sunt nule nu sunt serializate.

@JsonPropertyOrder — Această adnotare vă permite să setați ordinea în care sunt serializate câmpurile:


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

Rezultatul serializării:

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

Pentru moment, amintiți-vă cum să utilizați adnotările. La sfârșitul acestui modul, îi vom cunoaște mai bine și chiar vom crea propriile noastre adnotări.

Serializarea și deserializarea în XML

Dacă trebuie să serializăm în XML, putem folosi toate aceleași setări și adnotări. Singura diferență va fi implementareaobiect mapper:


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

Ieșire:

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

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

Serializarea și deserializarea în YAML

Tratăm YAML în același mod în care gestionăm 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);
}

Ieșire:

---
titlu: "Good Omens"
autor: "Pratchett T., Gaiman N."
pagini: 383

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