GP Coder

Trang chia sẻ kiến thức lập trình Java

  • Java Core
    • Basic Java
    • OOP
    • Exception Handling
    • Multi-Thread
    • Java I/O
    • Networking
    • Reflection
    • Collection
    • Java 8
  • Design pattern
    • Creational Pattern
    • Structuaral Pattern
    • Behavior Pattern
  • Web Service
    • SOAP
    • REST
  • JPA
  • Java library
    • Report
    • Json
    • Unit Test
  • Message Queue
    • ActiveMQ
    • RabbitMQ
  • All
Trang chủ Java library Json Hướng dẫn sử dụng Jackson Json Annotations

Hướng dẫn sử dụng Jackson Json Annotations

Đăng vào 28/01/2018 . Được đăng bởi GP Coder . 25318 Lượt xem . Toàn màn hình

Trong bài trước, tôi đã hướng dẫn các bạn sử dụng thư viện Jackson để chuyển đổi từ đối tượng Java sang JSON và từ JSON sang đối tượng Java. Trong bài này, tôi sẽ hướng dẫn bạn sử dụng các Annotation (chú thích) có sẵn của thư viện Jackson để tùy chỉnh quá trình chuyển đổi giữa các đối tượng Java và các đối tượng JSON.

Nội dung

  • 1 Ví dụ sử dụng Jackson Annotations
  • 2 Các Annotation được sử dụng trong ví dụ

Ví dụ sử dụng Jackson Annotations

Account.java


package com.gpcoder.jackson.object;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.gpcoder.jackson.annotation.CustomDateDeserializer;
import com.gpcoder.jackson.annotation.CustomDateSerializer;

@JsonIgnoreProperties({ "iban", "pin" })
public class Account {

	@JsonProperty("number")
	private String accountNumber;

	private String iban;

	private String pin;

	@JsonIgnore
	private String owner;

	@JsonProperty
	private String address;

	@JsonProperty
	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
	private Date createdDate;

	@JsonSerialize(using = CustomDateSerializer.class)
	@JsonDeserialize(using = CustomDateDeserializer.class)
	private Date expiredDate;

	private String notAnnotation;

	private String notAnnotationWithSetter;

	@JsonProperty
	private List<String> services = new ArrayList<String>();

	private Map<String, Object> history = new HashMap<String, Object>();

	@JsonAnyGetter
	public Map<String, Object> any() {
		return history;
	}

	@JsonAnySetter
	public void set(String name, Object value) {
		history.put(name, value);
	}

	public void setAccountNumber(String accountNumber) {
		this.accountNumber = accountNumber;
	}

	public void setIban(String iban) {
		this.iban = iban;
	}

	public void setPin(String pin) {
		this.pin = pin;
	}

	public void setOwner(String owner) {
		this.owner = owner;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public void setServices(List<String> services) {
		this.services = services;
	}

	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	public void setExpiredDate(Date expiredDate) {
		this.expiredDate = expiredDate;
	}

	public void setHistory(Map<String, Object> history) {
		this.history = history;
	}

	public String getNotAnnotationWithSetter() {
		return notAnnotationWithSetter;
	}

	@Override
	public String toString() {
		return "Account [accountNumber=" + accountNumber + ", iban=" + iban + ", pin=" + pin + ", owner=" + owner
				+ ", address=" + address + ", createdDate=" + createdDate + ", expiredDate=" + expiredDate
				+ ", notAnnotation=" + notAnnotation + ", notAnnotationWithSetter=" + notAnnotationWithSetter
				+ ", services=" + services + ", history=" + history + "]";
	}

}


CustomDateSerializer.java


package com.gpcoder.jackson.annotation;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class CustomDateSerializer extends JsonSerializer&lt;Date&gt; {

	private static final SimpleDateFormat dateFormat = new SimpleDateFormat(&quot;dd/MM/yyyy&quot;);

	@Override
	public void serialize(Date date, JsonGenerator generator, SerializerProvider provider)
			throws IOException, JsonProcessingException {
		String formattedDate = dateFormat.format(date);
		generator.writeString(formattedDate);
	}

}

CustomDateDeserializer.java


package com.gpcoder.jackson.annotation;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

public class CustomDateDeserializer extends JsonDeserializer&lt;Date&gt; {

	private static final SimpleDateFormat dateFormat = new SimpleDateFormat(&quot;dd/MM/yyyy&quot;);

	@Override
	public Date deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {
		final String dateString = jsonparser.getText();
		try {
			return dateFormat.parse(dateString);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

}

JacksonAnnotationExample.java


package com.gpcoder.jackson.annotation;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gpcoder.jackson.object.Account;

public class JacksonAnnotationExample {

	public static final String JSON_FILE = "data/result.json";

	public static void main(String args[]) throws JsonParseException, JsonMappingException, IOException {
		Account account = getAccount();

		// Convert Object to JSON string
		ObjectMapper mapper = new ObjectMapper();
		mapper.writerWithDefaultPrettyPrinter().writeValue(new File(JSON_FILE), account);

		// Convert a JSON to a Object
		String jsonString = "{" + 
				"\"address\" : \"Can Tho, Viet Nam\"," + 
				"\"createdDate\" : \"28/01/2018\"," + 
				"\"expiredDate\" : \"28/01/2018\"," + 
				"\"notAnnotationWithSetter\" : null," + 
				"\"services\" : [ \"Internet Banking\", \"Mobile Banking\" ]," + 
				"\"number\" : \"A123 4567 8909\"," + 
				"\"20180128\" : \"Change password\"," + 
				"\"20180101\" : \"Withdraw 100$\"," + 
				"\"add_1\" : \"Add unknown key 1\"," + 
				"\"add_2\" : \"Add unknown key 2\"" + 
				"}";
		// Account account2 = mapper.readValue(new File(JSON_FILE), Account.class);
		Account account2 = mapper.readValue(jsonString, Account.class);
		System.out.println(account2);

	}

	private static Account getAccount() {
		Account account = new Account();
		account.setAccountNumber("A123 4567 8909");
		account.setIban("IB 11 22 33 44");
		account.setOwner("GP Coder");
		account.setPin("123456");
		account.setAddress("Can Tho, Viet Nam");
		account.setCreatedDate(Calendar.getInstance().getTime());
		account.setExpiredDate(Calendar.getInstance().getTime());

		String[] services = { "Internet Banking", "Mobile Banking" };
		account.setServices(Arrays.asList(services));

		Map<String, Object> history = new HashMap<>();
		history.put("20180101", "Withdraw 100$");
		history.put("20180128", "Change password");
		account.setHistory(history);

		return account;
	}
}

Kết quả thực thi chương trình trên: result.json được tạo ra trong thư mục data. Nội dung của file result.json như sau:

[json]

{
“address” : “Can Tho, Viet Nam”,
“createdDate” : “28/01/2018”,
“expiredDate” : “28/01/2018”,
“notAnnotationWithSetter” : null,
“services” : [ “Internet Banking”, “Mobile Banking” ],
“number” : “A123 4567 8909”,
“20180128” : “Change password”,
“20180101” : “Withdraw 100$”
}

[/json]

Nội dung của console như sau:


Account [accountNumber=A123 4567 8909, 
iban=null, 
pin=null, 
owner=null, 
address=Can Tho, Viet Nam, 
createdDate=Sun Jan 28 07:00:00 ICT 2018, 
expiredDate=Sun Jan 28 00:00:00 ICT 2018, 
notAnnotation=null, 
notAnnotationWithSetter=null, 
services=[Internet Banking, Mobile Banking], 
history={add_2=Add unknown key 2, 20180128=Change password, 
add_1=Add unknown key 1, 20180101=Withdraw 100$}]

 

Các Annotation được sử dụng trong ví dụ

@JsonProperty

Chú thích này có thể được sử dụng trên một thuộc tính (field) hoặc phương thức (method) sẽ được sử dụng cho việc Serialization and Deserialization dữ liệu JSON. Nó có một tham số tùy chọn là tên khóa, tùy chọn này hữu ích trong trường hợp tên field khác với tên của khóa (key) trong JSON.

Khi nào sử dụng:
– Nếu bạn chỉ muốn khai báo thuộc tính và không phải là getter / setters.
– Nếu bạn đang sử dụng thuộc tính và getter / setters nhưng muốn sử dụng một tên getter / setter hoặc property khác với tên của key trong JSON. Chỉ cần đặt tham số tên trong các Annotation với tên key thực tế trong JSON.

Ví dụ ở trên tôi sử dụng thuộc tính @JsonProperty cho các field: accountNumber, address, createdDate, expiredDate, services. Các field này sẽ được Serialize sang chuỗi JSON.

Theo mặc định, Jackson sẽ lấy tên của field làm key của chuỗi JSON. Tuy nhiên chúng ta có thể thay đổi tên key nằm bằng cách sử dụng như field accountNumber trong ví dụ trên.

Trong ví dụ trên, các bạn cũng thấy là 2 field notAnnotation và notAnnotationWithSetter không được đánh dấu Annotation @JsonProperty nhưng field notAnnotationWithSetter được Serialize vì Jackson mặc định kiểm tra nếu field có @JsonProperty hoặc Getters sẽ được Serialize. Trong trường hợp này, field notAnnotation không có Annotation @JsonProperty cũng không có Getters nên không được Serialize, field notAnnotationWithSetter không có Annotation @JsonProperty nhưng có Getters nên được Serialize.

@JsonIgnoreProperties/ @JsonIgnore

@JsonIgnoreProperties: Chú thích cấp lớp (class) này có thể được sử dụng để loại trừ các thuộc tính nhất định trong quá trình Serialization and Deserialization dữ liệu JSON. Nghĩa là chúng sẽ không được ánh xạ tới nội dung JSON.

@JsonIgnore: chú thích cấp thuộc tính (field) này cũng được sử dụng để lại trừ field trong quá trình Serialization and Deserialization dữ liệu JSON.

Khi nào sử dụng:
– Nếu bạn muốn bỏ qua serialization / deserialization của một vài field nhất định.

Ví dụ ở trên tôi sử dụng @JsonIgnoreProperties({ “iban”, “pin” }) ở mức class hoặc sử dụng @JsonIgnore owner để loại trừ các field này khỏi quá trình Serialize chuỗi JSON.

@JsonAnySetter, @JsonAnyGetter

Những chú thích này hoạt động như một Catch-All và được áp dụng trên Getters / Setter làm việc với một Map. Nếu có bất kỳ giá trị JSON nào không được ánh xạ tới một thuộc tính trong Object, thì giá trị đó có thể bị bắt bởi @JsonAnySetter và được lưu trữ (deserialized) vào Map. Tương tự, các giá trị được lưu trữ trong Map có thể được tuần tự (serialized) trở lại JSON bằng @JsonAnyGetter.

Khi nào sử dụng:
– Nếu bạn không muốn khai báo một thuộc tính hoặc phương thức cho mọi khóa (key) có thể có trong JSON, nhưng vẫn muốn serialize/ deserialize dữ liệu.

Ví dụ ở trên, các JSON key: add_1, add_2, 20180128, 20180101 không có trong field của Object. Nhưng bằng cách sử dụng @JsonAnySetter & @JsonAnyGetter, chúng ta có thể serialize và deserialize các đối tượng này thông qua Map.

@JsonSerialize/ @JsonDeserialize

Hai chú thích này có thể được sử dụng để tùy chỉnh quá trình serialization/ deserialization mặc định (Java to JSON).

Khi nào sử dụng:
– Khi serialization/ deserialization mặc định không phù hợp với nhu cầu của bạn và bạn muốn có tùy chỉnh được áp dụng.

Ví dụ ở trên, tôi muốn expiredDate hiển thị định dạng dd/MM/yyyy. Nếu sử dụng Serialize thì không có được định dạng như mong muốn. Do đó, tôi đã viết lớp CustomDateSerializer để tùy chỉnh định dạng kiểu Date sang chuỗi dd/MM/yyyy của Json và lớp CustomDateDeserializer để tùy việc đọc chuỗi ngày dd/MM/yyyy sang kiểu Date của Java. Để 2 lớp này có hiệu lực, chúng ta cần đánh dấu @JsonSerialize(using = CustomDateSerializer.class) và @JsonDeserialize(using = CustomDateDeserializer.class) trên field expiredDate.

@JsonFormat

Đối với kiểu Date, ngoài việc sử dụng custom serialization/ deserialization như trên, Jackson có cung cấp một Annotation @JsonFormat để tùy chỉnh format dữ liệu kiểu Date/Time.

Khi nào sử dụng:
– Khi serialization/ deserialization dữ liệu mặc định không phù hợp và cần tùy chỉnh hiển thị nội dung kiểu Date/Time.

Ví dụ ở trên, field createdDate được đánh dấu @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = “dd/MM/yyyy”). Kết quả cũng tương tự như việc thực hiện tạo 2 lớp custom JsonSerializer và JsonDeserializer.

Một vài Annotation khác

@JsonGetter

Chú thích @JsonGetter là một thay thế cho chú thích @JsonProperty để đánh dấu ở phương thức (method) được chỉ định như một phương thức getter.


public class Student {
    private String name;
 
	@JsonProperty("name")
    public String getName() {
        return name;
    }
}

// Một cách viết khác

public class Student {
    private String name;
 
    @JsonGetter("name")
    public String getName() {
        return name;
    }
}

@JsonSetter

@JsonSetter là một sự thay thế cho @JsonProperty được sử dụng để đánh dấu phương thức (method) như một phương thức setter.


public class Student {
    private String name;
 
	@JsonProperty("name")
    public String getName() {
        return name;
    }
}

// Một cách viết khác

public class Student {
    private String name;
 
    @JsonSetter("name")
    public void setName() {
        this.name = name;
    }
}

@JsonPropertyOrder

Chú giải @JsonPropertyOrder được sử dụng để xác định thứ tự của thuộc tính được Serialize sang JSON.

@JsonPropertyOrder({ "name", "id" })
public class JsonPropertyOrderExample {
    public int id;
    public String name;
}

Kết quả hiển thị:

[json]

{
“name”:”GP Coder”,
“id”:1
}

[/json]

@JsonRootName

Chú thích @JsonRootName được sử dụng để chỉ định tên của wrapper gốc sẽ được sử dụng.


package com.gpcoder.jackson.annotation;

import com.fasterxml.jackson.annotation.JsonRootName;

@JsonRootName(value = "root")
public class JsonRootNameExample {
	public int id;
    public String name;
}

Kết quả hiển thị:

[json]

{
“root”: {
“name”:”GP Coder”,
“id”:1
}
}

[/json]

Trên đây là một vài các Annotation thường sử dụng. Ngoài ra còn nhiều Annotaion khác, các bạn hãy tham khảo thêm trên JavaDocs của thư viện Jackson.

Tài liệu tham khảo:

  • https://github.com/FasterXML/jackson-annotations
  • http://www.baeldung.com/jackson-annotations
5.0
03
Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé! Và Donate tác giả

Shares

Chuyên mục: Json Được gắn thẻ: Annotation, Jackson, json

Hướng dẫn sử dụng thư viện Jackson
Hướng dẫn Jackson Streaming API để đọc và ghi JSON

Có thể bạn muốn xem:

  • Hướng dẫn Gson Streaming API để đọc và ghi JSON (08/01/2018)
  • Hướng dẫn Jackson Streaming API để đọc và ghi JSON (31/01/2018)
  • Hướng dẫn sử dụng Gson TypeAdapter (18/01/2018)
  • Hướng dẫn sử dụng Gson Annotations (12/01/2018)
  • Hướng dẫn sử dụng thư viện Gson (06/01/2018)

Bình luận

bình luận

Tìm kiếm

Bài viết mới

  • Clean code 13/01/2024
  • Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud 02/10/2020
  • Kết nối RabbitMQ sử dụng Web STOMP Plugin 19/06/2020
  • Sử dụng publisher confirm trong RabbitMQ 16/06/2020
  • Sử dụng Dead Letter Exchange trong RabbitMQ 13/06/2020

Xem nhiều

  • Hướng dẫn Java Design Pattern – Factory Method (97351 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (96986 lượt xem)
  • Giới thiệu Design Patterns (86648 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (85486 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (83024 lượt xem)

Nội dung bài viết

  • 1 Ví dụ sử dụng Jackson Annotations
  • 2 Các Annotation được sử dụng trong ví dụ

Lưu trữ

Thẻ đánh dấu

Annotation Authentication Basic Java Behavior Pattern Collection Creational Design Pattern Cấu trúc điều khiển Database Dependency Injection Design pattern Eclipse Exception Executor Service Google Guice Gson Hibernate How to Interceptor IO Jackson Java 8 Java Core JDBC JDK Jersey JMS JPA json JUnit JWT Message Queue Mockito Multithreading OOP PowerMockito RabbitMQ Reflection Report REST SOAP Structuaral Pattern Swagger Thread Pool Unit Test Webservice

Liên kết

  • Clean Code
  • JavaTpoint
  • Refactoring Guru
  • Source Making
  • TutorialsPoint
  • W3Schools Online Web Tutorials

Giới thiệu

GP Coder là trang web cá nhân, được thành lập với mục đích lưu trữ, chia sẽ kiến thức đã học và làm việc của tôi. Các bài viết trên trang này chủ yếu về ngôn ngữ Java và các công nghệ có liên quan đến Java như: Spring, JSF, Web Services, Unit Test, Hibernate, SQL, ...
Hi vọng góp được chút ít công sức cho sự phát triển cộng đồng Coder Việt.

Donate tác giả

Tìm kiếm các bài viết của GP Coder với Google Search

Liên hệ

Các bạn có thể liên hệ với tôi thông qua:
  • Trang liên hệ
  • Linkedin: gpcoder
  • Email: contact@gpcoder.com
  • Skype: ptgiang56it

Follow me

Copyright 2025 © GP Coder · All Rights Reserved · Giới thiệu · Chính sách · Điều khoản · Liên hệ ·

Share

Blogger
Delicious
Digg
Email
Facebook
Facebook messenger
Flipboard
Google
Hacker News
Line
LinkedIn
Mastodon
Mix
Odnoklassniki
PDF
Pinterest
Pocket
Print
Reddit
Renren
Short link
SMS
Skype
Telegram
Tumblr
Twitter
VKontakte
wechat
Weibo
WhatsApp
X
Xing
Yahoo! Mail

Copy short link

Copy link