Jackson là một thư viện phổ biến để tuần tự hóa/giải tuần tự hóa các đối tượng Java thành các định dạng văn bản khác nhau. Lớp ObjectMapper là cách chính của thư viện để làm việc với định dạng JSON. Đối với các định dạng khác, chúng tôi có hậu duệ của nó ( XmlMapper , YAMLMapper ). Nhờ tính kế thừa, chúng tôi có thể làm việc với tất cả các định dạng một cách nhất quán, thông qua một giao diện duy nhất.

Tải xuống tệp jar

Trước khi nghiên cứu các ví dụ, chúng ta cần tải xuống các tệp Jackson jar và kết nối chúng với dự án trong IntelliJ IDEA. Hãy lấy ví dụ về jackson-databind để xem cách tìm kiếm các tệp cần thiết:

  1. Truy cập trang web Kho lưu trữ Maven .

  2. Nhập " jackson-databind " vào hộp tìm kiếm. Bạn sẽ nhận được những điều sau đây:

  3. Kết quả tìm kiếm đầu tiên là những gì chúng tôi quan tâm. Theo liên kết.

  4. Đôi khi một phiên bản cụ thể của thư viện có thể được yêu cầu để đảm bảo khả năng tương thích với các thành phần khác trong dự án. Phiên bản mới nhất sẽ hoạt động (tại thời điểm viết bài này là 2.13.2.2). Theo liên kết.

  5. Trên trang mở ra, bạn muốn liên kết "gói":

  6. Tải xuống tệp jar bằng liên kết này .

Theo quy trình tương tự, bạn có thể tìm và tải xuống phần còn lại của các tệp jar cần thiết:

Sau khi tải xuống tất cả các tệp cần thiết, hãy kết nối chúng với dự án trong IntelliJ IDEA:

  1. Mở cài đặt dự án (bạn có thể thực hiện với tổ hợp phím Ctrl+Alt+Shift+S ).

  2. Chuyển đến Thư viện .

  3. Nhấn + rồi nhấn "Java". Chọn tất cả các tệp đã tải xuống. Đây là những gì chúng ta nên kết thúc với:

  4. Điều đó kết thúc công việc chuẩn bị của chúng tôi. Bây giờ chúng ta có thể dùng thử ObjectMapper trong thực tế.

Tuần tự hóa thành JSON

Trước tiên, hãy tuần tự hóa một số đối tượng thành 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);
	}
}

Chạy chính sẽ cung cấp cho bạn đầu ra này:

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

ObjectMapper có rất nhiều cài đặt nâng cao . Hãy sử dụng một trong số chúng để làm cho chuỗi JSON dễ đọc hơn. Sau khi tạoObjectMapperđối tượng, hãy thực hiện câu lệnh này:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

Thông tin trong đầu ra vẫn giữ nguyên, nhưng bây giờ có thụt đầu dòng và ngắt dòng:

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

Giải tuần tự hóa từ JSON

Bây giờ hãy thực hiện hành động ngược lại: chúng ta sẽ giải tuần tự hóa một chuỗi thành một đối tượng. Để có thể xem chương trình đang làm gì, hãy ghi đè phương thức toString trong lớp Book :


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

Và chúng ta sẽ làm như sau trong phương thức chính :


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

Đầu ra:

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

Phương thức readValue bị quá tải — nó có nhiều biến thể lấy một tệp, một liên kết, nhiều luồng đầu vào, v.v. Để đơn giản, ví dụ của chúng tôi sử dụng một biến thể chấp nhận chuỗi JSON.

Như đã đề cập ở trên, ObjectMapper có nhiều cài đặt. Hãy xem xét một vài trong số họ.

Bỏ qua các thuộc tính không xác định

Hãy xem xét một tình huống trong đó một chuỗi JSON có một thuộc tính không tồn tại trong lớp Sách :


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

Việc thực thi mã này mang lại cho chúng tôi một ngoại lệ UnrecognizedPropertyException . Đây là hành vi mặc định, nhưng chúng ta có thể thay đổi nó:


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

Khi tạo mộtObjectMapperđối tượng, chúng tôi sử dụng phương thức cấu hình để đặt cài đặt tương ứng thành false . Phương thức cấu hình sửa đổi đối tượng mà nó được gọi và sau đó trả về cùng một đối tượng đó, vì vậy chúng ta có thể thực hiện cuộc gọi này theo một cách khác:


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

Về chức năng, ký hiệu này giống như ký hiệu trước.

Nếu bây giờ chúng ta chạy phương thức chính , quá trình khử lưu huỳnh sẽ thành công và thuộc tính không xác định sẽ bị bỏ qua.

chú thích thuận tiện

Jackson cung cấp cho chúng tôi một số chú thích cho phép chúng tôi tùy chỉnh quy trình lập số sê-ri theo mọi cách. Chúng ta hãy xem một số trong những cái hữu ích nhất:

@JsonIgnore — Chú thích này được đặt phía trên một phần tử cần được bỏ qua trong quá trình tuần tự hóa/giải tuần tự hóa:


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

đâytác giảtrường sẽ không được đưa vào JSON kết quả trong quá trình tuần tự hóa. Sau khi khử lưu huỳnh,tác giảtrường sẽ nhận giá trị mặc định (null), ngay cả khi JSON có giá trị khác.

@JsonFormat — Chú thích này cho phép bạn đặt định dạng của dữ liệu được tuần tự hóa. Hãy thêm một trường nữa, Date , vào lớp Book :


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

Sau khi tuần tự hóa, chúng tôi nhận được JSON sau:

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

Như bạn có thể thấy, ngày được đánh số theo thứ tự. Chúng tôi sẽ thêm một chú thích và đặt định dạng:


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

Bây giờ kết quả của tuần tự hóa là:

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

@JsonProperty — Chú thích này cho phép bạn thay đổi tên của thuộc tính đại diện cho trường được tuần tự hóa. Bạn cũng có thể đánh dấu các phương thức bằng chú thích này. Nếu bạn làm như vậy, thì giá trị trả về của chúng sẽ được chuyển đổi thành thuộc tính JSON trong quá trình tuần tự hóa:


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

Kết quả số hóa:

{
  "tác giả" : "Pratchett T., Gaiman N.",
  "pages" : 383,
  "name" : "Good Omens",
  "quotedTitle" : "\"Good Omens\""
}

@JsonInclude — Sử dụng chú thích này, bạn có thể chỉ định các điều kiện phải được đáp ứng để một trường được đánh số thứ tự. Bạn có thể áp dụng nó cho các trường riêng lẻ hoặc toàn bộ lớp. Trước tiên, hãy thử tuần tự hóa một đối tượng với các trường chưa được khởi tạo:


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

Kết quả số hóa:

{
  "tiêu đề" : null,
  "tác giả" : null,
  "trang" : 0
}

Và nếu bạn thêm chú thích:


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

Sau đó, chúng tôi nhận được kết quả này:

{
  "trang" : 0
}

Bây giờ các trường rỗng không được đánh số thứ tự.

@JsonPropertyOrder — Chú thích này cho phép bạn đặt thứ tự các trường được sắp xếp theo thứ tự:


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

Kết quả số hóa:

{
  "tác giả" : "Pratchett T., Gaiman N.",
  "title" : "Good Omens",
  "pages" : 383
}

Hiện tại, bạn chỉ cần nhớ cách sử dụng chú thích. Khi kết thúc mô-đun này, chúng ta sẽ hiểu rõ hơn về chúng và thậm chí tạo các chú thích của riêng mình.

Tuần tự hóa và giải tuần tự hóa trong XML

Nếu chúng tôi cần tuần tự hóa thành XML, chúng tôi có thể sử dụng tất cả các cài đặt và chú thích giống nhau. Sự khác biệt duy nhất sẽ là việc thực hiện cácđối tượng ánh xạ:


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

Đầu ra:

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

Giải tuần tự hóa 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);
}

Tuần tự hóa và giải tuần tự hóa trong YAML

Chúng tôi xử lý YAML giống như cách chúng tôi xử lý 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);
}

Đầu ra:

---
tiêu đề: "Good Omens"
tác giả: "Pratchett T., Gaiman N."
trang: 383

Khử lưu huỳnh của 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);
}