Jackson ialah perpustakaan popular untuk mensiri/menyahserialisasikan objek Java ke dalam pelbagai format teks. Kelas ObjectMapper ialah cara utama perpustakaan untuk berfungsi dengan format JSON . Untuk format lain, kami mempunyai keturunannya ( XmlMapper , YAMLMapper ). Terima kasih kepada warisan, kami boleh bekerja dengan semua format dengan cara yang konsisten, melalui antara muka tunggal.

Muat turun fail jar

Sebelum mengkaji contoh, kita perlu memuat turun fail balang Jackson dan menyambungkannya ke projek dalam IntelliJ IDEA. Mari kita ambil contoh jackson-databind untuk melihat cara mencari fail yang diperlukan:

  1. Pergi ke laman web Repositori Maven .

  2. Masukkan " jackson-databind " ke dalam kotak carian. Anda akan mendapat perkara berikut:

  3. Hasil carian pertama adalah perkara yang kami minati. Ikuti pautan.

  4. Kadangkala versi perpustakaan tertentu mungkin diperlukan untuk memastikan keserasian dengan komponen lain dalam projek. Versi terkini harus berfungsi (pada masa menulis pelajaran ini, ia adalah 2.13.2.2). Ikut pautan.

  5. Pada halaman yang terbuka, anda mahukan pautan "himpunan":

  6. Muat turun fail jar menggunakan pautan ini .

Mengikuti prosedur yang sama, anda boleh mencari dan memuat turun baki fail jar yang diperlukan:

Selepas memuat turun semua fail yang diperlukan, sambungkannya ke projek dalam IntelliJ IDEA:

  1. Buka tetapan projek (anda boleh lakukan dengan kombinasi kekunci Ctrl+Alt+Shift+S ).

  2. Pergi ke Perpustakaan .

  3. Tekan + dan kemudian "Java". Pilih semua fail yang dimuat turun. Inilah yang harus kita selesaikan:

  4. Itu menyimpulkan kerja persediaan kami. Sekarang kita boleh mencuba ObjectMapper dalam tindakan.

Pensirian kepada JSON

Mula-mula, mari kita sirikan beberapa objek ke 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);
	}
}

Running main akan memberi anda output ini:

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

ObjectMapper mempunyai banyak tetapan lanjutan . Mari gunakan salah satu daripadanya untuk menjadikan rentetan JSON lebih mudah dibaca. Selepas menciptaObjectMapperobjek, laksanakan pernyataan ini:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Maklumat dalam output tetap sama, tetapi kini terdapat lekukan dan pemisah baris:

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

Penyahserikatan daripada JSON

Sekarang mari kita lakukan tindakan yang bertentangan: kita akan menyahsiri rentetan menjadi objek. Untuk dapat melihat apa yang program sedang lakukan, mari kita ganti kaedah toString dalam kelas Buku :


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

Dan kami akan melakukan perkara berikut dalam kaedah utama :


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

Pengeluaran:

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

Kaedah readValue terlebih beban — ia mempunyai banyak variasi yang mengambil fail, pautan, pelbagai aliran input, dll. Untuk kesederhanaan, contoh kami menggunakan varian yang menerima rentetan JSON.

Seperti yang dinyatakan di atas, ObjectMapper mempunyai banyak tetapan. Mari lihat beberapa daripada mereka.

Mengabaikan sifat yang tidak diketahui

Pertimbangkan situasi di mana rentetan JSON mempunyai sifat yang tidak wujud dalam kelas Buku :


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

Melaksanakan kod ini memberi kami UnrecognizedPropertyException . Ini ialah tingkah laku lalai, tetapi kita boleh mengubahnya:


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

Apabila mencipta sebuahObjectMapperobjek, kami menggunakan kaedah konfigurasi untuk menetapkan tetapan yang sepadan kepada false . Kaedah konfigurasi mengubah suai objek yang dipanggil dan kemudian mengembalikan objek yang sama, jadi kita boleh membuat panggilan ini dengan cara yang berbeza:


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

Dari segi kefungsian, notasi ini sama seperti yang sebelumnya.

Jika sekarang kita menjalankan kaedah utama , penyahserialisasian akan berjaya dan harta yang tidak diketahui akan diabaikan.

Anotasi yang mudah

Jackson memberikan kami beberapa anotasi yang membolehkan kami menyesuaikan proses bersiri dalam pelbagai cara. Mari kita lihat beberapa yang paling berguna:

@JsonIgnore — Anotasi ini diletakkan di atas elemen yang harus diabaikan semasa bersiri/deserialisasi:


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

Di sinipengarangmedan tidak akan disertakan dalam JSON yang terhasil semasa bersiri. Selepas penyahserikatan, yangpengarangmedan akan mendapat nilai lalai (null), walaupun JSON mempunyai nilai yang berbeza.

@JsonFormat — Anotasi ini membolehkan anda menetapkan format data bersiri. Mari tambah satu lagi medan, Tarikh , pada kelas Buku :


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

Selepas bersiri, kami mendapat JSON berikut:

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

Seperti yang anda boleh lihat, tarikh itu telah bersiri sebagai nombor. Kami akan menambah anotasi dan menetapkan 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();
}

Sekarang hasil siri ialah:

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

@JsonProperty — Anotasi ini membolehkan anda menukar nama harta yang mewakili medan bersiri. Anda juga boleh menandakan kaedah dengan anotasi ini. Jika anda berbuat demikian, maka nilai pulangannya akan ditukar menjadi sifat JSON semasa penyirian:


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

Hasil seralisasi:

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

@JsonInclude — Menggunakan anotasi ini, anda boleh menentukan syarat yang mesti dipenuhi untuk sesuatu medan disirikan. Anda boleh menggunakannya pada medan individu atau keseluruhan kelas. Mula-mula, mari cuba mensirikan objek dengan medan yang tidak dimulakan:


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

Hasil seralisasi:

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

Dan jika anda menambah anotasi:


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

Kemudian kita mendapat hasil ini:

{
  "halaman" : 0
}

Sekarang medan yang batal tidak bersiri.

@JsonPropertyOrder — Anotasi ini membolehkan anda menetapkan susunan medan yang bersiri:


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

Hasil seralisasi:

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

Buat masa ini, cuma ingat cara menggunakan anotasi. Pada penghujung modul ini, kami akan mengenali mereka dengan lebih baik dan juga membuat anotasi kami sendiri.

Pensirian dan penyahserikatan dalam XML

Jika kita perlu bersiri ke dalam XML, kita boleh menggunakan semua tetapan dan anotasi yang sama. Satu-satunya perbezaan adalah pelaksanaannyaobjek pemeta:


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

Pengeluaran:

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

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

Pensirian dan penyahserikatan dalam YAML

Kami mengendalikan YAML dengan cara yang sama kami mengendalikan 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);
}

Pengeluaran:

---
tajuk: "Pertanda Baik"
pengarang: "Pratchett T., Gaiman N."
muka surat: 383

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