jackson介绍
引入類庫
ext {
? ? jacksonVersion = '2.9.5'
}
dependencies {
? ? compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: jacksonVersion
? ? compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: jacksonVersion
? ? compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: jacksonVersion
? ? // 引入XML功能
? ? compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: jacksonVersion
? ? // 比JDK自帶XML實現更高效的類庫
? ? compile group: 'com.fasterxml.woodstox', name: 'woodstox-core', version: '5.1.0'
? ? // Java 8 新功能
? ? compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: jacksonVersion
? ? compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-parameter-names', version: jacksonVersion
? ? compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jdk8', version: jacksonVersion
? ? compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.16.22'
}
Jackson注解
Jackson類庫包含了很多注解,可以讓我們快速建立Java類與JSON之間的關系。詳細文檔可以參考Jackson-Annotations。下面介紹一下常用的。
屬性命名
@JsonProperty注解指定一個屬性用于JSON映射,默認情況下映射的JSON屬性與注解的屬性名稱相同,不過可以使用該注解的value值修改JSON屬性名,該注解還有一個index屬性指定生成JSON屬性的順序,如果有必要的話。
屬性包含
還有一些注解可以管理在映射JSON的時候包含或排除某些屬性,下面介紹一下常用的幾個。
@JsonIgnore注解用于排除某個屬性,這樣該屬性就不會被Jackson序列化和反序列化。
@JsonIgnoreProperties注解是類注解。在序列化為JSON的時候,@JsonIgnoreProperties({"prop1", "prop2"})會忽略pro1和pro2兩個屬性。在從JSON反序列化為Java類的時候,@JsonIgnoreProperties(ignoreUnknown=true)會忽略所有沒有Getter和Setter的屬性。該注解在Java類和JSON不完全匹配的時候很有用。
@JsonIgnoreType也是類注解,會排除所有指定類型的屬性。
序列化相關
@JsonPropertyOrder和@JsonProperty的index屬性類似,指定屬性序列化時的順序。
@JsonRootName注解用于指定JSON根屬性的名稱。
?
處理JSON
簡單映射
ObjectMapper mapper = new ObjectMapper();Friend friend = new Friend("yitian", 25);// 寫為字符串String text = mapper.writeValueAsString(friend);// 寫為文件mapper.writeValue(new File("friend.json"), friend);// 寫為字節流byte[] bytes = mapper.writeValueAsBytes(friend);System.out.println(text);// 從字符串中讀取Friend newFriend = mapper.readValue(text, Friend.class);// 從字節流中讀取newFriend = mapper.readValue(bytes, Friend.class);// 從文件中讀取newFriend = mapper.readValue(new File("friend.json"), Friend.class);System.out.println(newFriend);輸出:
{"nickname":"yitian","age":25}
Friend(nickname=yitian, age=25)
集合的映射
除了使用Java類進行映射之外,我們還可以直接使用Map和List等Java集合組織JSON數據,在需要的時候可以使用readTree方法直接讀取JSON中的某個屬性值。需要注意的是從JSON轉換為Map對象的時候,由于Java的類型擦除,所以類型需要我們手動用new TypeReference<T>給出。
?
輸出:
{"name":"yitian","interests":["pc games","music"],"age":25}
{name=yitian, interests=[pc games, music], age=25}
name:yitian age:25
?
Jackson配置
Jackson預定義了一些配置,我們通過啟用和禁用某些屬性可以修改Jackson運行的某些行為。詳細文檔參考JacksonFeatures。下面我簡單翻譯一下Jackson README上列出的一些屬性。
// 美化輸出 mapper.enable(SerializationFeature.INDENT_OUTPUT); // 允許序列化空的POJO類 // (否則會拋出異常) mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // 把java.util.Date, Calendar輸出為數字(時間戳) mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);// 在遇到未知屬性的時候不拋出異常 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // 強制JSON 空字符串("")轉換為null對象值: mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);// 在JSON中允許C/C++ 樣式的注釋(非標準,默認禁用) mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); // 允許沒有引號的字段名(非標準) mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // 允許單引號(非標準) mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); // 強制轉義非ASCII字符 mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true); // 將內容包裹為一個JSON屬性,屬性名由@JsonRootName注解指定 mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);Java8日期時間類支持
Java8增加了一套全新的日期時間類,Jackson對此也有支持。這些支持是以Jackson模塊形式提供的,所以首先就是注冊這些模塊。
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()).registerModule(new ParameterNamesModule()).registerModule(new Jdk8Module());導入類庫之后,Jackson也可以自動搜索所有模塊,不需要我們手動注冊。
mapper.findAndRegisterModules();?
@JsonFormat(pattern = "yyyy/MM/DD")private LocalDate birthday;static void java8DateTime() throws IOException {Person p1 = new Person("yitian", "易天", 25, "10000", LocalDate.of(1994, 1, 1));ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());//mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);String text = mapper.writeValueAsString(p1);System.out.println(text);Person p2 = mapper.readValue(text, Person.class);System.out.println(p2);}輸出:
{"birthday":[1994,1,1],"Name":"yitian","NickName":"易天","Age":25,"IdentityCode":"10000"}
Person(name=yitian, nickname=易天, age=25, identityCode=10000, birthday=1994-01-01)
?
禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
則輸出:
{"birthday":"1994-01-01","Name":"yitian","NickName":"易天","Age":25,"IdentityCode":"10000"}
Person(name=yitian, nickname=易天, age=25, identityCode=10000, birthday=1994-01-01)
Spring Boot集成
自動配置
Spring Boot對Jackson的支持非常完善,只要我們引入相應類庫,Spring Boot就可以自動配置開箱即用的Bean。Spring自動配置的ObjectMapper(或者XmlMapper)作了如下配置,基本上可以適應大部分情況。
- 禁用了MapperFeature.DEFAULT_VIEW_INCLUSION
- 禁用了DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
- 禁用了SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
如果需要修改自動配置的ObjectMapper屬性也非常簡單,Spring Boot提供了一組環境變量,直接在application.properties文件中修改即可。
?
com.fasterxml.jackson.databind.DeserializationFeature|spring.jackson.deserialization.=true|false
com.fasterxml.jackson.core.JsonGenerator.Feature|spring.jackson.generator.=true|false
com.fasterxml.jackson.databind.MapperFeature|spring.jackson.mapper.=true|false
com.fasterxml.jackson.core.JsonParser.Feature|spring.jackson.parser.=true|false
com.fasterxml.jackson.databind.SerializationFeature|spring.jackson.serialization.=true|false
com.fasterxml.jackson.annotation.JsonInclude.Include|spring.jackson.default-property-inclusion=always|non_null|non_absent|non_default|non_empty
?
坑
getter,setter的影響
如果一個字段僅有getter,沒有setter,則會一個字段會產生2個json對象,一個名稱是全小寫的,一個是自己定義的。
?
?
總結
- 上一篇: Spring Cloud异常
- 下一篇: 开发管理工具