詳解jackson註解(一)jackson系列化註解
jackson中用於系列化的主要註解有:
註解 | 描述 | |
---|---|---|
1 | @JsonAnyGetter | @JsonAnyGetter註解可以靈活地把類型爲Map的屬性作爲標準屬性使用。 |
2 | @JsonGetter | @JsonProperty註解的替代方法,用於將方法標記爲getter方法。 |
3 | @JsonPropertyOrder | 指定系列化時各個屬性的順序 |
4 | @JsonRawValue | 可以指示Jackson完全按原樣序列化屬性 |
5 | @JsonValue | @JsonValue 可以用在get方法或者屬性字段上,一個類只能用一個,當加上@JsonValue註解時,序列化是隻返回這一個字段的值。 |
6 | @JsonRootName | 如果啓用了包裝,使用@JsonRootName註解指定要使用的根包裝的名稱。 |
上面的這些描述有一些可能不容易理解,看看下面的案例就理解了。
(一)@JsonAnyGetter
@JsonAnyGetter註解可以靈活地把類型爲Map的屬性作爲標準屬性使用。
1、在bean的map屬性上添加@JsonAnyGetter註解:
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import java.io.Serializable;
import java.util.Map;
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
public class User implements Serializable {
public String name;
private Map<String, String> properties;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 在map屬性上添加@JsonAnyGetter
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
public User() {
}
public User(String name) {
this.name = name;
}
}
2、controller中:
@GetMapping("/test1")
public User test() {
User user = new User("小明");
Map<String,String> map = new HashMap<String,String>();
map.put("age", "120");
map.put("address", "中國");
user.setProperties(map);
return user;
}
3、使用Postman請求,得到的響應:
{
"name": "小明",
"address": "中國",
"age": "120"
}
將bean的map中的屬性都提取出來當做了bean的標準屬性。好處就是靈活,不改bean的前提下可以靈活地設置系列化屬性。
(二)@JsonGetter
@JsonProperty註解的替代方法,用於將方法標記爲getter方法。
public class User {
public int id;
private String name;
@JsonGetter("name")
public String getTheName() {
return name;
}
// ......
}
(三)@JsonPropertyOrder
指定系列化時各個屬性的順序
1、bean
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
@Data
// 指定各個屬性在系列化時的順序
@JsonPropertyOrder({"name", "email", "phone", "address"})
public class User {
private String name;
private String address;
private String email;
private String phone;
}
2、controller
@GetMapping("/test2")
public User test2() {
User user = new User();
user.setName("chushiyan");
user.setEmail("chushiyan0415#163.com");
user.setPhone("18812345678");
user.setAddress("中國");
return user;
}
響應的json按照了@JsonPropertyOrder指定的順序:
{
"name": "chushiyan",
"email": "chushiyan0415#163.com",
"phone": "18812345678",
"address": "中國"
}
(四)@JsonRawValue
可以指示Jackson完全按原樣序列化屬性
1、bean
import com.fasterxml.jackson.annotation.JsonRawValue;
import lombok.Data;
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
@Data
public class Admin {
public String name;
@JsonRawValue
public String json;
}
2、controller
@GetMapping("/test5")
public Admin test5(){
Admin admin = new Admin();
admin.setName("chushiyan");
admin.setJson("{\"attr\":true}");
return admin;
}
postman請求返回的響應:
{
"name": "chushiyan",
"json": {
"attr": true
}
}
(五)@JsonValue
@JsonValue 可以用在get方法或者屬性字段上,一個類只能用一個,當加上@JsonValue註解時,序列化是隻返回這一個字段的值。
1、bean
import com.fasterxml.jackson.annotation.JsonValue;
import java.io.Serializable;
import lombok.Data;
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
@Data
public class Student implements Serializable {
private String name;
@JsonValue
private Integer score;
}
2、controller
@GetMapping("/test6")
public Student getStudent() {
Student student = new Student();
student.setName("chushiyan");
student.setScore(60);
return student;
}
3、postman請求返回的響應
60
注意:一個bean只能使用@JsonValue註解一個屬性,註解多個就會報錯:
com.fasterxml.jackson.databind.JsonMappingException: Problem with definition of [AnnotedClass com.chushiyan.test.entity.Student]: Multiple 'as-value' properties defined ([field com.chushiyan.test.entity.Student#name] vs [field com.chushiyan.test.entity.Student#score])
(六)@JsonRootName
如果啓用了包裝,使用@JsonRootName註解指定要使用的根包裝的名稱。
例如,定義一個People類,通常系列化後是這樣的:
{
"id": "1",
"name": "chushiyan"
}
如果想系列化下面這個樣子呢?
{
"people": {
"id": "1",
"name": "chushiyan"
}
}
這時,就可以使用@JsonRootName了。
1、bean
import com.fasterxml.jackson.annotation.JsonRootName;
/**
* @author chushiyan
* @email Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
* @description
*/
@Data
@JsonRootName(value = "people") // 默認是類名
public class People {
private String id;
private String name;
}
2、controller
@GetMapping("/people")
public People test3() {
People people = new People("1", "chushiyan");
return people;
}
然而,響應的結果不是我們希望的:
{
"id": "1",
"name": "chushiyan"
}
因爲還需要相應的配置,因爲使用@JsonRootName的前提就是啓用了包裝:
spring.jackson.serialization.wrap-root-value=true
或者yml中:
spring:
jackson:
serialization:
wrap-root-value: true
再次請求,返回的結果就是我們需要的了。
{
"people": {
"id": "1",
"name": "chushiyan"
}
}
注意:一旦在配置了spring.jackson.serialization.wrap-root-value=true,所有的響應都成了這種json樣式,哪怕報錯了:
{
"Map": {
"timestamp": "2019-12-01T07:36:50.164+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/test/people1"
}
}