Jackson adalah perpustakaan populer untuk serialisasi/deserialisasi objek Java ke dalam berbagai format teks. Kelas ObjectMapper adalah cara utama perpustakaan untuk bekerja dengan format JSON . Untuk format lain, kami memiliki turunannya ( XmlMapper , YAMLMapper ). Berkat pewarisan, kami dapat bekerja dengan semua format secara konsisten, melalui satu antarmuka.

Unduh file jar

Sebelum mempelajari contoh-contohnya, kita perlu mengunduh file Jackson jar dan menghubungkannya ke proyek di IntelliJ IDEA. Mari kita ambil contoh jackson-databind untuk melihat cara mencari file yang diperlukan:

  1. Buka situs web Repositori Maven .

  2. Masukkan " jackson-databind " ke dalam kotak pencarian. Anda akan mendapatkan yang berikut ini:

  3. Hasil pencarian pertama adalah yang kami minati. Ikuti tautannya.

  4. Terkadang versi perpustakaan tertentu mungkin diperlukan untuk memastikan kompatibilitas dengan komponen lain dalam sebuah proyek. Versi terbaru seharusnya berfungsi (pada saat menulis pelajaran ini, ini adalah 2.13.2.2). Ikuti tautannya.

  5. Pada halaman yang terbuka, Anda menginginkan tautan "bundel":

  6. Unduh file jar menggunakan tautan ini .

Mengikuti prosedur serupa, Anda dapat menemukan dan mengunduh sisa file jar yang diperlukan:

Setelah mengunduh semua file yang diperlukan, sambungkan ke proyek di IntelliJ IDEA:

  1. Buka pengaturan proyek (Anda dapat melakukannya dengan kombinasi tombol Ctrl+Alt+Shift+S ).

  2. Pergi ke Perpustakaan .

  3. Tekan + lalu "Java". Pilih semua file yang diunduh. Inilah yang harus kita akhiri:

  4. Itu menyimpulkan pekerjaan persiapan kami. Sekarang kita bisa mencoba ObjectMapper beraksi.

Serialisasi ke JSON

Pertama, mari buat serialisasi 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);
	}
}

Menjalankan main akan memberi Anda hasil ini:

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

ObjectMapper memiliki banyak pengaturan lanjutan . Mari gunakan salah satunya untuk membuat string JSON lebih mudah dibaca. Setelah membuatPemeta Objekobjek, jalankan pernyataan ini:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Informasi dalam keluaran tetap sama, tetapi sekarang ada lekukan dan jeda baris:

{
  "title" : "Pertanda Baik",
  "penulis" : "Pratchett T., Gaiman N.",
 "pages" : 383
}

Deserialisasi dari JSON

Sekarang mari kita lakukan tindakan sebaliknya: kita akan melakukan deserialisasi sebuah string menjadi sebuah objek. Untuk dapat melihat apa yang dilakukan program, mari kita ganti metode toString di kelas Book :


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

Dan kami akan melakukan hal berikut dalam metode 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);
}

Keluaran:

Buku{title='Pertanda Baik', pengarang='Pratchett T., Gaiman N.', pages=383}

Metode readValue kelebihan muatan — metode ini memiliki banyak variasi yang menggunakan file, link, berbagai input stream, dll. Untuk memudahkan, contoh kita menggunakan varian yang menerima string JSON.

Seperti disebutkan di atas, ObjectMapper memiliki banyak pengaturan. Mari kita lihat beberapa di antaranya.

Mengabaikan properti yang tidak diketahui

Pertimbangkan situasi di mana string JSON memiliki properti yang tidak ada di 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);
}

Menjalankan kode ini memberi kita UnrecognizedPropertyException . Ini adalah perilaku default, tetapi kita dapat mengubahnya:


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

Saat membuat sebuahPemeta Objekobjek, kami menggunakan metode configure untuk menyetel pengaturan yang sesuai ke false . Metode configure memodifikasi objek yang dipanggil dan kemudian mengembalikan objek yang sama, sehingga kita dapat melakukan panggilan ini dengan cara yang berbeda:


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

Dari segi fungsionalitas, notasi ini sama seperti notasi sebelumnya.

Jika sekarang kita menjalankan metode utama , deserialisasi akan berhasil dan properti yang tidak diketahui akan diabaikan.

Anotasi yang nyaman

Jackson memberi kami beberapa anotasi yang memungkinkan kami menyesuaikan proses serialisasi dengan berbagai cara. Mari kita lihat beberapa yang paling berguna:

@JsonIgnore — Anotasi ini ditempatkan di atas elemen yang harus diabaikan selama serialisasi/deserialisasi:


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

Di sinipengarangbidang tidak akan disertakan dalam JSON yang dihasilkan selama serialisasi. Setelah deserialization, thepengarangbidang akan mendapatkan nilai default (null), meskipun JSON memiliki nilai yang berbeda.

@JsonFormat — Anotasi ini memungkinkan Anda mengatur format data berseri. Mari tambahkan satu field lagi, sebuah Date , ke kelas Book :


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

Setelah serialisasi, kami mendapatkan JSON berikut:

 {
  "title" : "Pertanda Baik",
  "penulis" : "Pratchett T., Gaiman N.",
  "pages" : 383,
  "createdDate" : 1649330880788
}

Seperti yang Anda lihat, tanggal itu diserialkan sebagai angka. Kami akan menambahkan anotasi dan mengatur formatnya:


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 serialisasi adalah:

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

@JsonProperty — Anotasi ini memungkinkan Anda mengubah nama properti yang mewakili bidang berseri. Anda juga dapat menandai metode dengan anotasi ini. Jika Anda melakukannya, maka nilai pengembaliannya akan diubah menjadi properti JSON selama serialisasi:


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

Hasil seralisasi:

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

@JsonInclude — Dengan menggunakan anotasi ini, Anda dapat menentukan ketentuan yang harus dipenuhi agar bidang dapat diserialisasi. Anda dapat menerapkannya ke masing-masing bidang atau seluruh kelas. Pertama, mari kita coba membuat serial objek dengan bidang yang belum diinisialisasi:


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:

{
  "judul" : null,
  "pengarang" : null,
  "halaman" : 0
}

Dan jika Anda menambahkan anotasi:


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

Kemudian kita mendapatkan hasil ini:

{
  "halaman" : 0
}

Sekarang bidang yang nol tidak diserialisasi.

@JsonPropertyOrder — Anotasi ini memungkinkan Anda mengatur urutan bidang yang diserialisasi:


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

Hasil seralisasi:

{
  "penulis" : "Pratchett T., Gaiman N.",
  "judul" : "Pertanda Baik",
  "halaman" : 383
}

Untuk saat ini, ingat saja cara menggunakan anotasi. Di akhir modul ini, kita akan mengenal mereka lebih baik dan bahkan membuat anotasi kita sendiri.

Serialisasi dan deserialisasi dalam XML

Jika kita perlu membuat cerita bersambung ke dalam XML, kita dapat menggunakan semua pengaturan dan anotasi yang sama. Satu-satunya perbedaan adalah implementasi dariobjek peta:


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

Keluaran:

 <Buku>
  <title>Pertanda Baik</title>
  <penulis>Pratchett T., Gaiman N.</author>
  <pages>383</pages>
</Book>

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

Serialisasi dan deserialisasi dalam YAML

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

Keluaran:

---
judul: "Pertanda Baik"
penulis: "Pratchett T., Gaiman N."
halaman: 383

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