Ang Jackson ay isang sikat na aklatan para sa pagse-serialize/pag-deserialize ng mga bagay sa Java sa iba't ibang mga format ng teksto. Ang klase ng ObjectMapper ay ang pangunahing paraan ng library upang gumana sa format na JSON. Para sa iba pang mga format, mayroon kaming mga inapo nito ( XmlMapper , YAMLMapper ). Salamat sa inheritance, makakapagtrabaho kami sa lahat ng format sa pare-parehong paraan, sa pamamagitan ng iisang interface.

Mag-download ng mga file ng jar

Bago pag-aralan ang mga halimbawa, kailangan nating mag-download ng mga file ng Jackson jar at ikonekta ang mga ito sa proyekto sa IntelliJ IDEA. Kunin natin ang halimbawa ng jackson-databind upang makita kung paano maghanap ng mga kinakailangang file:

  1. Pumunta sa website ng Maven Repository .

  2. Ipasok ang " jackson-databind " sa box para sa paghahanap. Makukuha mo ang sumusunod:

  3. Ang unang resulta ng paghahanap ay kung ano ang interesado kami. Sundin ang link.

  4. Minsan ang isang partikular na bersyon ng isang library ay maaaring kailanganin upang matiyak ang pagiging tugma sa iba pang mga bahagi sa isang proyekto. Dapat gumana ang pinakabagong bersyon (sa oras ng pagsulat ng araling ito, ito ay 2.13.2.2). Sundin ang link.

  5. Sa page na bubukas, gusto mo ang link na "bundle":

  6. I-download ang jar file gamit ang link na ito .

Kasunod ng katulad na pamamaraan, maaari mong mahanap at i-download ang natitirang mga kinakailangang jar file:

Pagkatapos i-download ang lahat ng kinakailangang file, ikonekta ang mga ito sa proyekto sa IntelliJ IDEA:

  1. Buksan ang mga setting ng proyekto (maaari mong gawin sa kumbinasyon ng Ctrl+Alt+Shift+S key).

  2. Pumunta sa Mga Aklatan .

  3. Pindutin ang + at pagkatapos ay "Java". Piliin ang lahat ng na-download na file. Narito ang dapat nating tapusin:

  4. Iyan ang nagtatapos sa aming gawaing paghahanda. Ngayon ay maaari nating subukan ang ObjectMapper sa aksyon.

Serialization sa JSON

Una, i-serialize natin ang ilang object sa 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);
	}
}

Ang pagpapatakbo ng pangunahing ay magbibigay sa iyo ng output na ito:

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

Ang ObjectMapper ay may maraming mga advanced na setting. Gamitin natin ang isa sa mga ito para gawing mas madaling mabasa ang string ng JSON. Matapos malikha angObjectMapperobject, isagawa ang pahayag na ito:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Ang impormasyon sa output ay nananatiling pareho, ngunit ngayon ay may indentation at line break:

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

Deserialization mula sa JSON

Ngayon gawin natin ang kabaligtaran na aksyon: gagawin nating deserialize ang isang string sa isang bagay. Upang makita kung ano ang ginagawa ng programa, i-override natin ang toString na paraan sa klase ng Aklat :


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

At gagawin namin ang sumusunod sa pangunahing pamamaraan:


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

Output:

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

Overloaded ang readValue method — marami itong variation na kumukuha ng file, link, iba't ibang input stream, atbp. Para sa pagiging simple, gumagamit ang aming halimbawa ng variant na tumatanggap ng JSON string.

Tulad ng nabanggit sa itaas, ang ObjectMapper ay may maraming mga setting. Tingnan natin ang ilan sa kanila.

Hindi pinapansin ang mga hindi kilalang katangian

Isaalang-alang ang isang sitwasyon kung saan ang isang JSON string ay may property na hindi umiiral sa klase ng Aklat :


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

Ang pagpapatupad ng code na ito ay nagbibigay sa amin ng UnrecognizedPropertyException . Ito ang default na gawi, ngunit maaari naming baguhin ito:


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

Kapag lumilikha ng isangObjectMapperobject, ginagamit namin ang paraan ng pag-configure upang itakda ang kaukulang setting sa false . Binabago ng paraan ng pag-configure ang object kung saan ito tinawag at pagkatapos ay ibabalik ang parehong bagay, para magawa natin ang tawag na ito sa ibang paraan:


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

Sa mga tuntunin ng pag-andar, ang notasyong ito ay katulad ng nauna.

Kung patakbuhin natin ngayon ang pangunahing pamamaraan, magtatagumpay ang deserialization at hindi papansinin ang hindi kilalang pag-aari .

Mga maginhawang anotasyon

Nagbibigay sa amin si Jackson ng ilang anotasyon na nagbibigay-daan sa aming i-customize ang proseso ng serialization sa lahat ng uri ng paraan. Tingnan natin ang ilan sa mga pinaka-kapaki-pakinabang:

@JsonIgnore — Ang anotasyong ito ay inilalagay sa itaas ng isang elemento na dapat balewalain sa panahon ng serialization/deserialization:


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

Dito angmay-akdahindi isasama ang field sa magreresultang JSON sa panahon ng serialization. Sa deserialization, angmay-akdamakukuha ng field ang default na value (null), kahit na may ibang value ang JSON.

@JsonFormat — Hinahayaan ka ng anotasyong ito na itakda ang format ng serialized na data. Magdagdag tayo ng isa pang field, isang Petsa , sa klase ng Aklat :


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

Pagkatapos ng serialization, nakukuha namin ang sumusunod na JSON:

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

Tulad ng nakikita mo, ang petsa ay na-serialize bilang isang numero. Magdaragdag kami ng anotasyon at itatakda ang format:


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

Ngayon ang resulta ng serialization ay:

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

@JsonProperty — Hinahayaan ka ng annotation na ito na baguhin ang pangalan ng property na kumakatawan sa serialized na field. Maaari mo ring markahan ang mga pamamaraan gamit ang anotasyong ito. Kung gagawin mo, ang kanilang return value ay mako-convert sa JSON property sa panahon ng serialization:


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

Resulta ng seralization:

{
  "may-akda" : "Pratchett T., Gaiman N.",
  "mga pahina" : 383,
  "pangalan" : "Good Omens",
  "quotedTitle" : "\"Good Omens\""
}

@JsonInclude — Gamit ang anotasyong ito, maaari mong tukuyin ang mga kundisyon na dapat matugunan para ma-serialize ang isang field. Maaari mo itong ilapat sa mga indibidwal na field o isang buong klase. Una, subukan nating i-serialize ang isang bagay na may mga hindi nasimulang field:


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

Resulta ng seralization:

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

At kung idagdag mo ang anotasyon:


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

Pagkatapos ay makuha namin ang resultang ito:

{
  "mga pahina" : 0
}

Ngayon ang mga field na null ay hindi serialized.

@JsonPropertyOrder — Hinahayaan ka ng annotation na ito na itakda ang pagkakasunud-sunod kung saan naka-serialize ang mga field:


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

Resulta ng seralization:

{
  "may-akda" : "Pratchett T., Gaiman N.",
  "title" : "Good Omens",
  "pages" : 383
}

Sa ngayon, tandaan lang kung paano gumamit ng mga anotasyon. Sa dulo ng modyul na ito, mas makikilala natin sila at gagawa pa tayo ng sarili nating mga anotasyon.

Serialization at deserialization sa XML

Kung kailangan naming mag-serialize sa XML, magagamit namin ang lahat ng parehong mga setting at anotasyon. Ang pagkakaiba lamang ay ang pagpapatupad ngobject ng 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);
}

Output:

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

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

Serialization at deserialization sa YAML

Pinangangasiwaan namin ang YAML sa parehong paraan na pinangangasiwaan namin ang 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);
}

Output:

---
pamagat: "Good Omens"
may-akda: "Pratchett T., Gaiman N."
mga pahina: 383

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