Jackson 常用注解
@JacksonInject
通過 @JacksonInject 注解可以在 Jackson 反序列化的時(shí)候?yàn)榭罩底侄蝿?dòng)態(tài)賦值,當(dāng)反序列化的對應(yīng)屬性值不存在時(shí),可通過該注解為其動(dòng)態(tài)設(shè)置值。
@Getter@Setterpublic class User {????@JacksonInject(value?=?"dynamic")????private?String?name;?????private?Integer?age;}
對其進(jìn)行反序列化:
public?class?JacksonInjectTest?{????private?static?final?ObjectMapper?MAPPER?=?new?ObjectMapper();?????public?static?void?main(String[]?args)?throws?JsonProcessingException?{????????//?名稱和注解中聲明的相同才行?????????InjectableValues.Std?injectableValues?=?new?InjectableValues.Std()?????????????????.addValue("dynamic",?"some?dynamic?value");?????????MAPPER.setInjectableValues(injectableValues);?????????//?反序列化空對象?????????User?u?=?MAPPER.readValue("{}",?User.class);?????????System.out.println(u.getName());}?}// 輸出結(jié)果:some dynamic value
@JsonAlias
通過 @JsonAlias 注解可以為對象屬性定義一個(gè)或多個(gè)別名,然后在反序列化時(shí)根據(jù)別名進(jìn)行屬性映射。但要注意,別名不能與其他屬性名沖突,否則反序列化時(shí)會拋異常。
@Getter@Setterpublic class User {?@JsonAlias(value = "nm")private String name;?private Integer age;?}
對其進(jìn)行反序列化:
public static void main(String[] args) throws JsonProcessingException {User u = MAPPER.readValue("{\"nm\":\"張三\"}", User.class);System.out.println(u.getName());}// 輸出結(jié)果:張三
@JsonAnyGetter、@JsonAnySetter
@JsonAnyGetter 注解可用于將一組鍵值對平鋪展開到常規(guī)屬性中,比如某個(gè)對象正常序列化的結(jié)果為:
{??"name":?"張三",???"info":?{????"address":?"china",????"age":?"25"??}?}
通過該注解修飾后,序列化后的結(jié)果為:
{??"name":?"張三",??"address":?"china",???"age":?"25"}
不過這個(gè)注解的使用也是有條件限制的:
被修飾的方法不能是靜態(tài)方法
被修飾的方法必須是無參方法
被修飾的方法返回值必須是 Map 類型
同一實(shí)體中只能有一個(gè)方法使用該注解
具體如下例所示:
public?class?User?{?????private?String?name;?private Map<String, String> info;?public Map<String, String> getInfo() {return info;}}
對該對象進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????Map?info?=?new?HashMap<>(); ????info.put("age",?"25");?????info.put("address",?"china");?????User?user?=?new?User();?????user.setName("張三");????user.setInfo(info);?????System.out.println(MAPPER.writeValueAsString(user));?}// 輸出結(jié)果:{"name":"張三","address":"china","age":"25"}
@JsonAnySetter
?注解的功能與 @JsonAnyGetter 正好相反,使用示例如下:
public class User {?private String name;???????? private?String?address;?private String age;??????????public?void?setInfo(Map<String,?String>?info)?{????????this.address?=?info.get("address");?????????this.age?=?info.get("age");}?}
對其進(jìn)行反序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?MAPPER.readValue("{\"name\":\"張三\",\"info\":{\"address\":\"china\",\"age\":\"25\"}}",?User.class);?????System.out.println(user.getAddress());}?// 輸出結(jié)果:china
@JsonAutoDetect
@JsonAutoDetect 注解可以用于強(qiáng)制序列化私有屬性,即使沒有提供 Getter 方法:
(fieldVisibility?=?JsonAutoDetect.Visibility.ANY)public?class?User?{private String name;private String age;?}
我們沒有為 User 提供 Getter 方法,對其進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.setName("張三");????user.setAge("25");System.out.println(MAPPER.writeValueAsString(user));?}// 輸出結(jié)果:{"name":"張三","age":"25"}
@JsonBackReference、@JsonManagedReference
@JsonManagedReference 注解和 @JsonBackReference 注解用于處理父子關(guān)系并解決對象間的循環(huán)引用,比如兩個(gè)類互相持有對方的場景:
public?class?User?{?private String name;????private Friend friend;?}?public class Friend {private String number;?????private User user;?}
對其進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.setName("張三");????Friend?friend?=?new?Friend();????friend.setNumber("001");????friend.setUser(user);????user.setFriend(friend);????System.out.println(MAPPER.writeValueAsString(user));}// 輸出結(jié)果:{"name":"張三","friend":{"number":"001"}}
@JsonCreator
Jackson 在反序列化時(shí)默認(rèn)會通過對象的無參構(gòu)造方法創(chuàng)建對象,如果想要通過自定義的構(gòu)造方法創(chuàng)建對象,需要通過 @JsonCreator 來指定構(gòu)造方法,并通過 @JsonProperty 設(shè)置構(gòu)造方法中參數(shù)對應(yīng)的 JSON 屬性名:
@Getterpublic class User {?private final String name;????private?final?String?age;?????@JsonCreator????public?User(@JsonProperty("name")?String?name,?@JsonProperty("age")?String?age)????????this.name?=?name;????????this.age?=?age;?????}}
反序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?MAPPER.readValue("{\"name\":\"張三\",\"age\":\"25\"}",?User.class);????System.out.println(user.getName());}?// 輸出結(jié)果:張三
@JsonEnumDefaultValue
反序列化時(shí),如果對應(yīng)的枚舉值不存在 Jackson 默認(rèn)會拋出異常。我們可以通過 @JsonEnumDefaultValue 注解為未知的枚舉類型賦一個(gè)默認(rèn)值來兜底,但要記得在 ObjectMapper 中手動(dòng)開啟該功能。
@Setter@Getterpublic?static?class?User?{????private?String?name;????private?Sex?sex;}?private?enum?Sex?{????MAN,????WOMAN,????@JsonEnumDefaultValue????UNKNOWN}
反序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????MAPPER.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);????User?user?=?MAPPER.readValue("{\"name\":\"張三\",\"sex\":\"NONE\"}",?User.class);????System.out.println(user.getSex());}// 輸出結(jié)果:UNKNOWN
@JsonFormat
默認(rèn)序列化會將 Date 類型解析成時(shí)間戳,如果是 Java 8 提供的 LocalDateTime 則默認(rèn)不支持序列化,需要額外注冊 Module 支持,可以通過?@JsonFormat?注解在序列化過程中對數(shù)據(jù)進(jìn)行格式化輸出:
格式化時(shí)間(只支持 Date 類型):
public static class User {?????(shape?=?JsonFormat.Shape.STRING,?pattern?=?"yyyy-MM-dd?HH:mm:ss",?timezone?=?"GMT+8")private Date birthday;?}?// 序列化輸出:{"birthday":"2021-09-06 21:13:42"}
格式化枚舉類型(默認(rèn)只輸出枚舉名稱,如果有枚舉屬性會忽略):
?
public?enum?Sex?{????MAN(1,?"男生"),????WOMAN(2,?"女生");?private final Integer code;?????private?final?String?description;?????Sex(Integer?code,?String?description)?{????????this.code?=?code;????????this.description?=?description;}?}// 序列化輸出:{"sex":{"code":1,"description":"男生"}}
@JsonGetter、@JsonSetter
@JsonGetter、@JsonSetter 注解用于在序列化和反序列化時(shí)指定屬性的 Getter 和 Setter 方法。特別針對有些不正規(guī)的方法:
public class User {?????private?String?name;?public String returnName() {return name;}?????????public?void?putName(String?name)?{????????this.name?=?name;}?}
User 類沒有提供標(biāo)準(zhǔn)的 Setter、Getter 方法,對其進(jìn)行序列化和反序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.putName("張三");????System.out.print(MAPPER.writeValueAsString(user));????User?userD?=?MAPPER.readValue("{\"name\":\"張三\"}",?User.class);????System.out.print(userD.returnName());}// 輸出結(jié)果:{"name":"張三"}張三
@JsonIdentityInfo
@JsonIdentityInfo 注解作用于類或?qū)傩陨希谛蛄谢⒎葱蛄谢瘯r(shí)可以為該對象或字段添加一個(gè)對象識別碼,比如 @id 或者 Class 對象名,主要用于解決字段循環(huán)嵌套的問題。
public class User {private String name;????private User friend;?}
循環(huán)嵌套后進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?userA?=?new?User();????userA.setName("張三");????User?userB?=?new?User();????userB.setName("李四");????//?循環(huán)引用????userA.setFriend(userB);????userB.setFriend(userA);????System.out.println(MAPPER.writeValueAsString(userA));}//?輸出結(jié)果:{??"name":?"張三",??"friend":?{????"@id":?"5eba3199-ed97-4642-81b8-ad7b61ed9fd8",????"name":?"李四",????"friend":?{??????"@id":?"fddcb9fa-c934-4735-8fec-2923675976cc",??????"name":?"張三",??????"friend":?"5eba3199-ed97-4642-81b8-ad7b61ed9fd8"}??}}
@JsonIgnore
@JsonIgnore 也是常用的一個(gè)注解,在序列化、反序列化時(shí)會忽略被該注解標(biāo)記的屬性。
public class User {?????????private?String?name;?private String age;?}
對其進(jìn)行序列化和反序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.setName("張三");????user.setAge("25");????System.out.print(MAPPER.writeValueAsString(user));????User?userD?=?MAPPER.readValue("{\"name\":\"張三\",\"age\":\"25\"}",?User.class);????System.out.print(userD.getName());}// 輸出結(jié)果:{"age":"25"}null
@JsonIgnoreProperties
@JsonIgnoreProperties 注解可以在序列化、反序列化時(shí)忽略多個(gè)屬性,通常標(biāo)記在類上。
({"name", "age"})public class User {?private String name;?private String age;?private String sex;?}// 序列化結(jié)果:{"sex":"男"}
如果有些屬性不太確定也可以通過該注解過濾掉,避免未知屬性異常:
@JsonIgnoreProperties(ignoreUnknown = true)此外,還提供了 allowGetters、allowSetters 屬性用于僅忽略 Setter 或 Getter:
@JsonIgnoreProperties(allowGetters = true, allowSetters = true)@JsonIgnoreType
@JsonIgnoreType 注解用于在序列化、反序列化時(shí)忽略掉某種特定類型,作用在類上,引用這個(gè)類的其他對象在序列化、反序列化時(shí)會忽略這個(gè)類,主要用來對一些數(shù)據(jù)敏感對象進(jìn)行忽略。
public?class?User?{?private String name;?private Hobby hobby;}?public?class?Hobby?{?private String item;?}
對其進(jìn)行序列化、反序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.setName("張三");?????Hobby?hobby?=?new?Hobby();????hobby.setItem("basketball");????user.setHobby(hobby);????System.out.print(MAPPER.writeValueAsString(user));????User?userD?=?MAPPER.readValue("{\"name\":\"張三\",\"hobby\":{\"item\":\"basketball\"}}",?User.class);????System.out.print(userD.getHobby()?==?null);}// 輸出結(jié)果:{"name":"張三"}true
@JsonInclude
@JsonInclude 注解用于標(biāo)識對象屬性何時(shí)可以被序列化,可以把該注解標(biāo)記在屬性字段上,也可以通過 ObjectMapper 的 setSerializationInclusion 方法進(jìn)行統(tǒng)一設(shè)置。Jackson 默認(rèn)會把空值字段序列化為 null,我們可以通過 JsonInclude.Include.NON_NULL 來過濾掉空值字段:
public class User {?private String name;?(JsonInclude.Include.NON_NULL)private String age;?}
對其進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.setName("張三");????System.out.println(MAPPER.writeValueAsString(user));}// 輸出結(jié)果:{"name":"張三"}
@JsonIncludeProperties
@JsonIncludeProperties 注解與 @JsonIgnoreProperties 注解正好相反,它只會在序列化、反序列化包含在注解中的屬性,其它屬性都不參與序列化和反序列化。
({"name",?"age"})public class User {???? private?String?name;?private String age;private String sex;?}
對其進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????User?user?=?new?User();????user.setName("張三");????user.setAge("25");?????user.setSex("男");?????System.out.println(MAPPER.writeValueAsString(user));}// 輸出結(jié)果:{"name":"張三","age":"25"}
@JsonProperty
@JsonProperty 也是常用注解,它包含了很多其他注解的功能,因此最好不要與功能重復(fù)的注解同時(shí)使用,以免產(chǎn)生干擾。該注解通常標(biāo)記在屬性或?qū)傩缘?Getter、Setter 方法上,功能如下:
可以在反序列化時(shí)指定屬性的名稱,類似 @JsonAlias 的效果。
public?class?User?{?????("nm")????private?String?name;?????private?String?age;?}?// 反序列化時(shí)可以將nm對應(yīng)的值賦值到name字段上
通過 Access 枚舉可以控制哪些屬性可以進(jìn)行序列化、反序列化,類似 @JsonIgnore 的效果。
public?class?User?{?????(access?=?JsonProperty.Access.READ_ONLY)private String name;private String age;?}// 因?yàn)閚ame屬性被設(shè)置為只讀,所以反序列化時(shí)會忽略name屬性
@JsonRawValue
@JsonRawValue 注解會將字符串形式的 JSON 也嘗試序列化為對象,示例如下:
?public class User {????private?String?name;?????private String json;?}
對其進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{?????User?user?=?new?User();?????user.setName("張三");?????user.setJson("{\"age\":\"25\"}");????System.out.println(MAPPER.writeValueAsString(user));}// 輸出結(jié)果:{??"name":?"張三",???"json":?{?????"age":?"25"???}?}//?如果沒有該注解修飾則輸出:{??"name":?"張三",???"json":?"{\"age\":\"25\"}"}
@JsonUnwrapped
@JsonUnwrapped 注解可以在序列化時(shí)把一個(gè)對象中嵌套對象的屬性平鋪展開,放到同一層級:
??public?static?class?User?{?private String name;??????private Identity identity;?}?public?static?class?Identity?{?????private?String?age;?private String address;?}
對其進(jìn)行序列化:
public static void main(String[] args) throws JsonProcessingException {?User user = new User();?user.setName("張三");?Identity identity = new Identity();?identity.setAge("25");?identity.setAddress("china");?user.setIdentity(identity);?System.out.println(MAPPER.writeValueAsString(user));?}// 輸出結(jié)果:{"name":"張三","age":"25","address":"china"}
@JsonFilter
@JsonFilter 注解用于指定在序列化期間要使用的過濾器:
("customFilter")public static class User {private String name;?private String age;?private String cardCode;private String address;?}
我們對 User 對象進(jìn)行序列化:
public?static?void?main(String[]?args)?throws?JsonProcessingException?{????SimpleBeanPropertyFilter?propertyFilter?=?SimpleBeanPropertyFilter.filterOutAllExcept("cardCode",?"address");????FilterProvider?provider?=?new?SimpleFilterProvider().addFilter("customFilter",?propertyFilter);????User?user?=?new?User();????user.setName("張三");????user.setAge("25");?????user.setAddress("china");?????user.setCardCode("123456");?????System.out.println(MAPPER.writer(provider).writeValueAsString(user));}// 輸出結(jié)果:{"cardCode":"123456","address":"china"}
@JsonAppend
@JsonAppend 注解可以在序列化時(shí)額外添加指定的屬性:
(attrs?=?{????.Attr(value?=?"version")????})public?class?User?{private String name;?private String age;?}
我們可以在序列化時(shí)手動(dòng)增加 version=1.0 的屬性值:
public static void main(String[] args) throws JsonProcessingException {User user = new User();user.setName("張三");user.setAge("25");String str = MAPPER.writerFor(User.class).withAttribute("version", "1.0").writeValueAsString(user);System.out.println(str);}// 輸出結(jié)果:{"name":"張三","age":"25","version":"1.0"}
記得點(diǎn)「贊」和「在看」↓
愛你們
