Jackson är ett populärt bibliotek för att serialisera/deserialisera Java-objekt till olika textformat. ObjectMapper - klassen är bibliotekets huvudsakliga sätt att arbeta med JSON-formatet. För andra format har vi dess ättlingar ( XmlMapper , YAMLMapper ). Tack vare arv kan vi arbeta med alla format på ett konsekvent sätt, genom ett enda gränssnitt.

Ladda ner jar-filer

Innan vi studerar exemplen måste vi ladda ner Jackson jar-filer och koppla dem till projektet i IntelliJ IDEA. Låt oss ta exemplet med jackson-databind för att se hur man söker efter nödvändiga filer:

  1. Gå till webbplatsen för Maven Repository .

  2. Skriv " jackson-databind " i sökrutan. Du får följande:

  3. Det första sökresultatet är det vi är intresserade av. Följ länken.

  4. Ibland kan en viss version av ett bibliotek krävas för att säkerställa kompatibilitet med andra komponenter i ett projekt. Den senaste versionen bör fungera (när den här lektionen skrivs är den 2.13.2.2). Följ länken.

  5. På sidan som öppnas vill du ha länken "bunt":

  6. Ladda ner jar-filen med denna länk .

Genom att följa en liknande procedur kan du hitta och ladda ner resten av de nödvändiga jar-filerna:

Efter att ha laddat ner alla nödvändiga filer, anslut dem till projektet i IntelliJ IDEA:

  1. Öppna projektinställningarna (du kan göra med tangentkombinationen Ctrl+Alt+Skift+S) .

  2. Gå till bibliotek .

  3. Tryck på + och sedan på "Java". Välj alla nedladdade filer. Här är vad vi bör sluta med:

  4. Därmed är vårt förberedande arbete avslutat. Nu kan vi prova ObjectMapper i aktion.

Serialisering till JSON

Låt oss först serialisera något objekt till 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);
	}
}

Att köra main ger dig denna utdata:

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

ObjectMapper har många avancerade inställningar . Låt oss använda en av dem för att göra JSON-strängen mer läsbar. Efter att ha skapatObjectMapperobjekt, kör detta uttalande:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Informationen i utgången förblir densamma, men nu finns det indrag och radbrytningar:

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

Deserialisering från JSON

Låt oss nu göra den motsatta åtgärden: vi deserialiserar en sträng till ett objekt. För att kunna se vad programmet gör, låt oss åsidosätta toString -metoden i klassen Book :


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

Och vi kommer att göra följande i huvudmetoden :


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:

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

ReadValue - metoden är överbelastad — den har många varianter som tar en fil, en länk, olika indataströmmar, etc. För enkelhetens skull använder vårt exempel en variant som accepterar en JSON-sträng.

Som nämnts ovan har ObjectMapper många inställningar. Låt oss titta på några av dem.

Ignorera okända egenskaper

Tänk på en situation där en JSON-sträng har en egenskap som inte finns 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);
}

Att köra den här koden ger oss ett UnrecognizedPropertyException . Detta är standardbeteendet, men vi kan ändra det:


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

När du skapar enObjectMapperobjekt använder vi konfigureringsmetoden för att ställa in motsvarande inställning på false . Konfigurationsmetoden modifierar objektet det anropades på och returnerar sedan samma objekt, så att vi kan göra det här anropet på ett annat sätt :


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

När det gäller funktionalitet är denna notation precis som den tidigare.

Om vi ​​nu kör huvudmetoden kommer deserialiseringen att lyckas och den okända egenskapen kommer att ignoreras.

Behändiga anteckningar

Jackson förser oss med flera kommentarer som gör att vi kan anpassa serialiseringsprocessen på alla möjliga sätt. Låt oss ta en titt på några av de mest användbara:

@JsonIgnore — Den här kommentaren placeras ovanför ett element som bör ignoreras under serialisering/deserialisering:


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

Härförfattarefältet kommer inte att inkluderas i den resulterande JSON under serialisering. Vid deserialisering,författarekommer att få standardvärdet (null), även om JSON hade ett annat värde.

@JsonFormat — Denna anteckning låter dig ställa in formatet för den serialiserade datan. Låt oss lägga till ytterligare ett fält, ett datum , till bokklassen :


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

Efter serialisering får vi följande JSON:

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

Som du kan se var datumet serialiserat som ett nummer. Vi lägger till en kommentar och ställer in 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 är resultatet av serialisering:

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

@JsonProperty — Den här anteckningen låter dig ändra namnet på egenskapen som representerar det serialiserade fältet. Du kan också markera metoder med denna anteckning. Om du gör det kommer deras returvärde att konverteras till 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 — Med den här anteckningen kan du ange villkor som måste uppfyllas för att ett fält ska serialiseras. Du kan tillämpa det på enskilda fält eller en hel klass. Låt oss först försöka serialisera ett objekt med oinitierade fält:


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
}

Och om du lägger till anteckningen:


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

Då får vi detta resultat:

{
  "sidor" : 0
}

Nu serialiseras inte fält som är null .

@JsonPropertyOrder — Den här kommentaren låter dig ställa in i vilken ordning fälten serialiseras:


@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
}

För nu, kom bara ihåg hur du använder kommentarer. I slutet av den här modulen kommer vi att lära känna dem bättre och till och med skapa våra egna kommentarer.

Serialisering och deserialisering i XML

Om vi ​​behöver serialisera till XML kan vi använda samma inställningar och anteckningar. Den enda skillnaden kommer att vara genomförandet avmapper 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:

 <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 och deserialisering i YAML

Vi hanterar YAML på samma sätt som vi hanterar 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"
författare: "Pratchett T., Gaiman N."
sidor: 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);
}