官方WIKI:https://github.com/FasterXML/jackson-databind/wiki
jackson 1.x和2.x版本的註解是放置在不同的包下的
1.x是在jackson core jar包org.codehaus.jackson.annotate下
2.x是在jackson-databind包com.fasterxml.jackson.annotation下
jackson的自動檢測機制
jackson允許使用任意的構造方法或工廠方法來構造實例
使用@JsonAutoDetect(作用在類上)來開啓/禁止自動檢測
fieldVisibility:字段的可見級別
ANY:任何級別的字段都可以自動識別
NONE:所有字段都不可以自動識別
NON_PRIVATE:非private修飾的字段可以自動識別
PROTECTED_AND_PUBLIC:被protected和public修飾的字段可以被自動識別
PUBLIC_ONLY:只有被public修飾的字段纔可以被自動識別
DEFAULT:同PUBLIC_ONLY
jackson默認的字段屬性發現規則如下:
所有被public修飾的字段->所有被public修飾的getter->所有被public修飾的setter
舉例:
- public static class TestPOJO{
- TestPOJO(){}
- TestPOJO(String name){
- this.name = name;
- }
- private String name;
- @Override
- public String toString() {
- return "TestPOJO{" +
- "name='" + name + '\'' +
- '}';
- }
- }
- @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
除了上面的方式,你還可以有一些其他方式可以配置methods,fields和creators(構造器和靜態方法)的自動檢測,例如:
你可以配置MapperFeature來啓動/禁止一些特別類型(getters,setters,fields,creators)的自動檢測
比如下面的MapperFeature配置:
SORT_PROPERTIES_ALPHABETICALLY:按字母順序排序屬性
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);
配置SerializationFeature
一些我們比較常用的SerializationFeature配置:
SerializationFeature.WRAP_ROOT_VALUE:是否環繞根元素,默認false,如果爲true,則默認以類名作爲根元素,你也可以通過@JsonRootName來自定義根元素名稱
- objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);
舉例:
- @JsonRootName("myPojo")
- public static class TestPOJO{
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
SerializationFeature.INDENT_OUTPUT:是否縮放排列輸出,默認false,有些場合爲了便於排版閱讀則需要對輸出做縮放排列
- objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
舉例:
如果一個類中有a、b、c、d四個可檢測到的屬性,那麼序列化後的json輸出類似下面:
{
"a" : "aaa",
"b" : "bbb",
"c" : "ccc",
"d" : "ddd"
}
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS:序列化日期時以timestamps輸出,默認true
- objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true);
SerializationFeature.WRITE_ENUMS_USING_TO_STRING:序列化枚舉是以toString()來輸出,默認false,即默認以name()來輸出
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
SerializationFeature.WRITE_ENUMS_USING_INDEX:序列化枚舉是以ordinal()來輸出,默認false
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,true);
舉例:
- @Test
- public void enumTest() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- testPOJO.setMyEnum(TestEnum.ENUM01);
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,false);
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false);
- String jsonStr1 = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"myEnum\":\"ENUM01\",\"name\":\"myName\"}",jsonStr1);
- ObjectMapper objectMapper2 = new ObjectMapper();
- objectMapper2.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
- String jsonStr2 = objectMapper2.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"myEnum\":\"enum_01\",\"name\":\"myName\"}",jsonStr2);
- ObjectMapper objectMapper3 = new ObjectMapper();
- objectMapper3.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,true);
- String jsonStr3 = objectMapper3.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"myEnum\":0,\"name\":\"myName\"}",jsonStr3);
- }
- public static class TestPOJO{
- TestPOJO(){}
- private TestEnum myEnum;
- private String name;
- //getters、setters省略
- }
- public static enum TestEnum{
- ENUM01("enum_01"),ENUM02("enum_01"),ENUM03("enum_01");
- private String title;
- TestEnum(String title) {
- this.title = title;
- }
- @Override
- public String toString() {
- return title;
- }
- }
SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED:序列化單元素數組時不以數組來輸出,默認false
- objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
- @Test
- public void singleElemArraysUnwrap() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- List<Integer> counts = new ArrayList<>();
- counts.add(1);
- testPOJO.setCounts(counts);
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,false);
- String jsonStr1 = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"counts\":[1]}",jsonStr1);
- ObjectMapper objectMapper2 = new ObjectMapper();
- objectMapper2.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,true);
- String jsonStr2 = objectMapper2.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"counts\":1}",jsonStr2);
- }
- public static class TestPOJO{
- private String name;
- private List<Integer> counts;
- //getters、setters省略
- }
SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS:序列化Map時對key進行排序操作,默認false
- objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);
- @Test
- public void orderMapBykey() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- Map<String,Integer> counts = new HashMap<>();
- counts.put("a",1);
- counts.put("d",4);
- counts.put("c",3);
- counts.put("b",2);
- counts.put("e",5);
- testPOJO.setCounts(counts);
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,false);
- String jsonStr1 = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"counts\":{\"d\":4,\"e\":5,\"b\":2,\"c\":3,\"a\":1}}",jsonStr1);
- ObjectMapper objectMapper2 = new ObjectMapper();
- objectMapper2.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);
- String jsonStr2 = objectMapper2.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"counts\":{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}}",jsonStr2);
- }
- public static class TestPOJO{
- private String name;
- private Map<String,Integer> counts;
- //getters、setters省略
- }
SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS:序列化char[]時以json數組輸出,默認false
- objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
- @Test
- public void charArraysAsJsonArrays() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- char[] counts = new char[]{'a','b','c','d'};
- testPOJO.setCounts(counts);
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,false);
- String jsonStr1 = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"counts\":\"abcd\"}",jsonStr1);
- ObjectMapper objectMapper2 = new ObjectMapper();
- objectMapper2.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
- String jsonStr2 = objectMapper2.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"counts\":[\"a\",\"b\",\"c\",\"d\"]}",jsonStr2);
- }
- public static class TestPOJO{
- private String name;
- private char[] counts;
- //getters、setters省略
- }
SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN:序列化BigDecimal時之間輸出原始數字還是科學計數,默認false,即是否以toPlainString()科學計數方式來輸出
- objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
- @Test
- public void bigDecimalAsPlain() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- testPOJO.setCount(new BigDecimal("1e20"));
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,false);
- String jsonStr1 = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"count\":1E+20}",jsonStr1);
- ObjectMapper objectMapper2 = new ObjectMapper();
- objectMapper2.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,true);
- String jsonStr2 = objectMapper2.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"name\":\"myName\",\"count\":100000000000000000000}",jsonStr2);
- }
反序列化的配置這裏不再多做解釋,參見點擊打開鏈接
需要注意的是對於第二種通過配置SerializationConfig和DeserializationConfig方式只能啓動/禁止自動檢測,無法修改我們所需的可見級別有時候對每個實例進行可見級別的註解可能會非常麻煩,這時候我們需要配置一個全局的可見級別,通過objectMapper.setVisibilityChecker()來實現,默認的VisibilityChecker實現類爲VisibilityChecker.Std,這樣可以滿足實現複雜場景下的基礎配置。
也有一些實用簡單的可見級別配置,比如:
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) // auto-detect all member fields
- .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE) // but only public getters
- .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE) // and none of "is-setters"
- ;
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.setVisibilityChecker(objectMapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
jackson的常用註解
1、@JsonAutoDetect
看上面自動檢測,不再重複
2、@JsonIgnore
作用在字段或方法上,用來完全忽略被註解的字段和方法對應的屬性,即便這個字段或方法可以被自動檢測到或者還有其他的註解
舉例
- @Test
- public void jsonIgnoreTest() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setId(111);
- testPOJO.setName("myName");
- testPOJO.setCount(22);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"id\":111}",jsonStr);
- String jsonStr2 = "{\"id\":111,\"name\":\"myName\",\"count\":22}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2, TestPOJO.class);
- Assert.assertEquals(111,testPOJO2.getId());
- Assert.assertNull(testPOJO2.getName());
- Assert.assertEquals(0,testPOJO2.getCount());
- }
- public static class TestPOJO{
- private int id;
- @JsonIgnore
- private String name;
- private int count;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getCount() {
- return count;
- }
- @JsonIgnore
- public void setCount(int count) {
- this.count = count;
- }
- }
3、@JsonProperty
作用在字段或方法上,用來對屬性的序列化/反序列化,可以用來避免遺漏屬性,同時提供對屬性名稱重命名,比如在很多場景下Java對象的屬性是按照規範的駝峯書寫,但是實際展示的卻是類似C-style或C++/Microsolft style
舉例
- @Test
- public void jsonPropertyTest() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.wahaha(111);
- testPOJO.setFirstName("myName");
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"id\":111,\"first_name\":\"myName\"}",jsonStr);
- String jsonStr2 = "{\"id\":111,\"first_name\":\"myName\"}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2, TestPOJO.class);
- Assert.assertEquals(111, testPOJO2.wahaha());
- Assert.assertEquals("myName", testPOJO2.getFirstName());
- }
- public static class TestPOJO{
- @JsonProperty//注意這裏必須得有該註解,因爲沒有提供對應的getId和setId函數,而是其他的getter和setter,防止遺漏該屬性
- private int id;
- @JsonProperty("first_name")
- private String firstName;
- public int wahaha() {
- return id;
- }
- public void wahaha(int id) {
- this.id = id;
- }
- public String getFirstName() {
- return firstName;
- }
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
- }
4、@JsonIgnoreProperties
作用在類上,用來說明有些屬性在序列化/反序列化時需要忽略掉,可以將它看做是@JsonIgnore的批量操作,但它的功能比@JsonIgnore要強,比如一個類是代理類,我們無法將將@JsonIgnore標記在屬性或方法上,此時便可用@JsonIgnoreProperties標註在類聲明上,它還有一個重要的功能是作用在反序列化時解析字段時過濾一些未知的屬性,否則通常情況下解析到我們定義的類不認識的屬性便會拋出異常。
可以註明是想要忽略的屬性列表如@JsonIgnoreProperties({"name","age","title"}),
也可以註明過濾掉未知的屬性如@JsonIgnoreProperties(ignoreUnknown=true)
舉例:
- @Test(expected = UnrecognizedPropertyException.class)
- public void JsonIgnoreProperties() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setId(111);
- testPOJO.setName("myName");
- testPOJO.setAge(22);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"id\":111}",jsonStr);//name和age被忽略掉了
- String jsonStr2 = "{\"id\":111,\"name\":\"myName\",\"age\":22,\"title\":\"myTitle\"}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2, TestPOJO.class);
- Assert.assertEquals(111, testPOJO2.getId());
- Assert.assertNull(testPOJO2.getName());
- Assert.assertEquals(0,testPOJO2.getAge());
- String jsonStr3 = "{\"id\":111,\"name\":\"myName\",\"count\":33}";//這裏有個未知的count屬性,反序列化會報錯
- objectMapper.readValue(jsonStr3, TestPOJO.class);
- }
- @JsonIgnoreProperties({"name","age","title"})
- public static class TestPOJO{
- private int id;
- private String name;
- private int age;
- //getters、setters省略
- }
- @JsonIgnoreProperties({"name","age","title"})
更換爲
- @JsonIgnoreProperties(ignoreUnknown=true)
5、@JsonUnwrapped
作用在屬性字段或方法上,用來將子JSON對象的屬性添加到封閉的JSON對象,說起來比較難懂,看個例子就很清楚了,不多解釋
舉例
- @Test
- public void jsonUnwrapped() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setId(111);
- TestName testName = new TestName();
- testName.setFirstName("張");
- testName.setSecondName("三");
- testPOJO.setName(testName);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- //如果沒有@JsonUnwrapped,序列化後將爲{"id":111,"name":{"firstName":"張","secondName":"三"}}
- //因爲在name屬性上加了@JsonUnwrapped,所以name的子屬性firstName和secondName將不會包含在name中。
- Assert.assertEquals("{\"id\":111,\"firstName\":\"張\",\"secondName\":\"三\"}",jsonStr);
- String jsonStr2 = "{\"id\":111,\"firstName\":\"張\",\"secondName\":\"三\"}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);
- Assert.assertEquals(111,testPOJO2.getId());
- Assert.assertEquals("張",testPOJO2.getName().getFirstName());
- Assert.assertEquals("三",testPOJO2.getName().getSecondName());
- }
- public static class TestPOJO{
- private int id;
- @JsonUnwrapped
- private TestName name;
- //getters、setters省略
- } public static class TestName{
- private String firstName;
- private String secondName;
- //getters、setters省略
- }
- @JsonUnwrapped(prefix = "name_",suffix = "_test")
6、@JsonIdentityInfo
2.0+版本新註解,作用於類或屬性上,被用來在序列化/反序列化時爲該對象或字段添加一個對象識別碼,通常是用來解決循環嵌套的問題,比如數據庫中的多對多關係,通過配置屬性generator來確定識別碼生成的方式,有簡單的,配置屬性property來確定識別碼的名稱,識別碼名稱沒有限制。
對象識別碼可以是虛擬的,即存在在JSON中,但不是POJO的一部分,這種情況下我們可以如此使用註解
- @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,property = "@id")
對象識別碼也可以是真實存在的,即以對象的屬性爲識別碼,通常這種情況下我們一般以id屬性爲識別碼,可以這麼使用註解
- @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
- @Test
- public void jsonIdentityInfo() throws Exception {
- Parent parent = new Parent();
- parent.setName("jack");
- Child child = new Child();
- child.setName("mike");
- Child[] children = new Child[]{child};
- parent.setChildren(children);
- child.setParent(parent);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(parent);
- Assert.assertEquals("{\"@id\":1,\"name\":\"jack\",\"children\":[{\"name\":\"mike\",\"parent\":1}]}",jsonStr);
- }
- @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,property = "@id")
- public static class Parent{
- private String name;
- private Child[] children;
- //getters、setters省略
- }
- public static class Child{
- private String name;
- private Parent parent;
- //getters、setters省略
- }
這裏需要提醒一下的是在1.6版本中提供了@JsonManagedReference和@JsonBackReference來解決循環嵌套問題,因爲屬於過時註解這裏就不解釋了,有興趣的可以自己看
7、@JsonNaming
jackson 2.1+版本的註解,作用於類或方法,注意這個註解是在jackson-databind包中而不是在jackson-annotations包裏,它可以讓你定製屬性命名策略,作用和前面提到的@JsonProperty的重命名屬性名稱相同。比如
你有一個JSON串{"in_reply_to_user_id":"abc123"},需要反序列化爲POJO,POJO一般情況下則需要如此寫
- public static class TestPOJO{
- private String in_reply_to_user_id;
- public String getIn_reply_to_user_id() {
- return in_reply_to_user_id;
- }
- public void setIn_reply_to_user_id(String in_reply_to_user_id) {
- this.in_reply_to_user_id = in_reply_to_user_id;
- }
- }
- public static class TestPOJO{
- @JsonProperty("in_reply_to_user_id")
- private String inReplyToUserId;
- public String getInReplyToUserId() {
- return inReplyToUserId;
- }
- public void setInReplyToUserId(String inReplyToUserId) {
- this.inReplyToUserId = inReplyToUserId;
- }
- }
舉例
- @Test
- public void jsonNaming() throws Exception{
- String jsonStr = "{\"in_reply_to_user_id\":\"abc123\"}";
- ObjectMapper objectMapper = new ObjectMapper();
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("abc123",testPOJO.getInReplyToUserId());
- TestPOJO testPOJO2 = new TestPOJO();
- testPOJO2.setInReplyToUserId("abc123");
- String jsonStr2 = objectMapper.writeValueAsString(testPOJO2);
- Assert.assertEquals(jsonStr,jsonStr2);
- }
- @JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
- public static class TestPOJO{
- private String inReplyToUserId;
- public String getInReplyToUserId() {
- return inReplyToUserId;
- }
- public void setInReplyToUserId(String inReplyToUserId) {
- this.inReplyToUserId = inReplyToUserId;
- }
- }
舉例
- @Test
- public void jsonNaming() throws Exception{
- String jsonStr = "{\"in-reply-to-user-id\":\"abc123\"}";
- ObjectMapper objectMapper = new ObjectMapper();
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("abc123", testPOJO.getInReplyToUserId());
- TestPOJO testPOJO2 = new TestPOJO();
- testPOJO2.setInReplyToUserId("abc123");
- String jsonStr2 = objectMapper.writeValueAsString(testPOJO2);
- Assert.assertEquals(jsonStr, jsonStr2);
- }
- @JsonNaming(MyPropertyNamingStrategy.class)
- public static class TestPOJO{
- private String inReplyToUserId;
- public String getInReplyToUserId() {
- return inReplyToUserId;
- }
- public void setInReplyToUserId(String inReplyToUserId) {
- this.inReplyToUserId = inReplyToUserId;
- }
- }
- public static class MyPropertyNamingStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
- @Override
- public String translate(String input) {
- if (input == null) return input; // garbage in, garbage out
- int length = input.length();
- StringBuilder result = new StringBuilder(length * 2);
- int resultLength = 0;
- boolean wasPrevTranslated = false;
- for (int i = 0; i < length; i++)
- {
- char c = input.charAt(i);
- if (i > 0 || c != '-') // skip first starting underscore
- {
- if (Character.isUpperCase(c))
- {
- if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '-')
- {
- result.append('-');
- resultLength++;
- }
- c = Character.toLowerCase(c);
- wasPrevTranslated = true;
- }
- else
- {
- wasPrevTranslated = false;
- }
- result.append(c);
- resultLength++;
- }
- }
- return resultLength > 0 ? result.toString() : input;
- }
- }
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy());
多態類型處理
jackson允許配置多態類型處理,當進行反序列話時,JSON數據匹配的對象可能有多個子類型,爲了正確的讀取對象的類型,我們需要添加一些類型信息。可以通過下面幾個註解來實現:
@JsonTypeInfo
作用於類/接口,被用來開啓多態類型處理,對基類/接口和子類/實現類都有效
- @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property = "name")
use:定義使用哪一種類型識別碼,它有下面幾個可選值:
1、JsonTypeInfo.Id.CLASS:使用完全限定類名做識別
2、JsonTypeInfo.Id.MINIMAL_CLASS:若基類和子類在同一包類,使用類名(忽略包名)作爲識別碼
3、JsonTypeInfo.Id.NAME:一個合乎邏輯的指定名稱
4、JsonTypeInfo.Id.CUSTOM:自定義識別碼,由@JsonTypeIdResolver對應,稍後解釋
5、JsonTypeInfo.Id.NONE:不使用識別碼
include(可選):指定識別碼是如何被包含進去的,它有下面幾個可選值:
1、JsonTypeInfo.As.PROPERTY:作爲數據的兄弟屬性
2、JsonTypeInfo.As.EXISTING_PROPERTY:作爲POJO中已經存在的屬性
3、JsonTypeInfo.As.EXTERNAL_PROPERTY:作爲擴展屬性
4、JsonTypeInfo.As.WRAPPER_OBJECT:作爲一個包裝的對象
5、JsonTypeInfo.As.WRAPPER_ARRAY:作爲一個包裝的數組
property(可選):制定識別碼的屬性名稱
此屬性只有當use爲JsonTypeInfo.Id.CLASS(若不指定property則默認爲@class)、JsonTypeInfo.Id.MINIMAL_CLASS(若不指定property則默認爲@c)、JsonTypeInfo.Id.NAME(若不指定property默認爲@type),include爲JsonTypeInfo.As.PROPERTY、JsonTypeInfo.As.EXISTING_PROPERTY、JsonTypeInfo.As.EXTERNAL_PROPERTY時纔有效
defaultImpl(可選):如果類型識別碼不存在或者無效,可以使用該屬性來制定反序列化時使用的默認類型
visible(可選,默認爲false):是否可見
屬性定義了類型標識符的值是否會通過JSON流成爲反序列化器的一部分,默認爲fale,也就是說,jackson會從JSON內容中處理和刪除類型標識符再傳遞給JsonDeserializer。
@JsonSubTypes
作用於類/接口,用來列出給定類的子類,只有當子類類型無法被檢測到時纔會使用它
一般是配合@JsonTypeInfo在基類上使用,比如:
- @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property = "typeName")
- @JsonSubTypes({@JsonSubTypes.Type(value=Sub1.class,name = "sub1"),@JsonSubTypes.Type(value=Sub2.class,name = "sub2")})
@JsonTypeName
作用於子類,用來爲多態子類指定類型標識符的值
比如:
- @JsonTypeName(value = "sub1")
@JsonTypeResolver和@JsonTypeIdResoler
作用於類,可以自定義多態的類型標識符,這個平時很少用到,主要是現有的一般就已經滿足絕大多數的需求了,如果你需要比較特別的類型標識符,建議使用這2個註解,自己定製基於TypeResolverBuilder和TypeIdResolver的類即可
我們看幾個jackson處理多態的例子
- @Test
- public void jsonTypeInfo() throws Exception{
- Sub1 sub1 = new Sub1();
- sub1.setId(1);
- sub1.setName("sub1Name");
- Sub2 sub2 = new Sub2();
- sub2.setId(2);
- sub2.setAge(33);
- ObjectMapper objectMapper = new ObjectMapper();
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setMyIns(new MyIn[]{sub1, sub2});
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"myIns\":[{\"id\":1,\"name\":\"sub1Name\"},{\"id\":2,\"age\":33}]}", jsonStr);
- System.out.println(jsonStr);
- }
- public static abstract class MyIn{
- private int id;
- //getters、setters省略
- }
- public static class Sub1 extends MyIn{
- private String name;
- //getters、setters省略
- }
- public static class Sub2 extends MyIn{
- private int age;
- //getters、setters省略
- }
下面我們在基類MyIn上加上多態處理相關注解,首先我們在基類MyIn上添加@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)即
- @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
- public static abstract class MyIn{
- private int id;
- //getters、setters省略
- }
{"myIns":[{"@class":"cn.yangyong.fodder.util.JacksonUtilsTest$Sub1","id":1,"name":"sub1Name"},{"@class":"cn.yangyong.fodder.util.JacksonUtilsTest$Sub2","id":2,"age":33}]}
我們可以看到多了相應的多態類型識別碼,識別碼名稱爲默認的@class(因爲沒有指定名稱),識別碼的值爲JsonTypeInfo.Id.CLASS即子類完全限定名
我們再添加上property屬性@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,property = "typeName")即
- @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,property = "typeName")
- public static abstract class MyIn{
- private int id;
- //getters、setters省略
- }
{"myIns":[{"typeName":"cn.yangyong.fodder.util.JacksonUtilsTest$Sub1","id":1,"name":"sub1Name"},{"typeName":"cn.yangyong.fodder.util.JacksonUtilsTest$Sub2","id":2,"age":33}]}
這次多態類型識別碼的名稱已經變成了我們指定的typeName而不是默認的@class了
上面的例子都是默認選擇的include爲JsonTypeInfo.As.PROPERTY,下面我們更改include方式,看看有什麼變化,將include設置爲JsonTypeInfo.As.WRAPPER_OBJECT即
- @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,include = JsonTypeInfo.As.WRAPPER_OBJECT,property = "typeName")
- public static abstract class MyIn{
- private int id;
- //getters、setters省略
- }
{"myIns":[{"cn.yangyong.fodder.util.JacksonUtilsTest$Sub1":{"id":1,"name":"sub1Name"}},{"cn.yangyong.fodder.util.JacksonUtilsTest$Sub2":{"id":2,"age":33}}]}
我們看到類型識別碼不再成爲兄弟屬性包含進去了而是爲父屬性將其他屬性包含進去,此時我們指定的property=“typeName”已經無用了
再次修改use屬性指定爲JsonTypeInfo.Id.MINIMAL_CLASS,即@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS,include = JsonTypeInfo.As.PROPERTY,property = "typeName")
- @JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS,include = JsonTypeInfo.As.PROPERTY,property = "typeName")
- public static abstract class MyIn{
- private int id;
- //getters、setters省略
- }
{"myIns":[{"typeName":".JacksonUtilsTest$Sub1","id":1,"name":"sub1Name"},{"typeName":".JacksonUtilsTest$Sub2","id":2,"age":33}]}
發現已經沒有同包的package名稱,識別碼的值更加簡短了
測試反序列化
- @Test
- public void jsonTypeInfo() throws Exception{
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr2 = "{\"myIns\":[{\"typeName\":\".JacksonUtilsTest$Sub1\",\"id\":1,\"name\":\"sub1Name\"},{\"typeName\":\".JacksonUtilsTest$Sub2\",\"id\":2,\"age\":33}]}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);
- MyIn[] myIns = testPOJO2.getMyIns();
- for (MyIn myIn : myIns) {
- System.out.println(myIn.getClass().getSimpleName());
- }
- }
可能我們在反序列化時覺得如此傳遞識別碼很不友好,最好可以自定義識別碼的值,可以選擇use = JsonTypeInfo.Id.NAME和@JsonSubTypes配合即
- @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property = "typeName")
- @JsonSubTypes({@JsonSubTypes.Type(value=Sub1.class,name="sub1"),@JsonSubTypes.Type(value=Sub2.class,name="sub2")})
- public static abstract class MyIn{
- private int id;
- //getters、setters省略
- }
{"myIns":[{"typeName":"sub1","id":1,"name":"sub1Name"},{"typeName":"sub2","id":2,"age":33}]}
使用這個結果反序列化也可以得到我們想要的結果,或者在子類上添加@JsonTypeName(value = "sub1")和@JsonTypeName(value = "sub2")以便取代@JsonSubTypes裏的name
如果想不使用@JsonSubTypes來實現反序列化,我們可以在ObjectMapper上註冊子類實現,即
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.registerSubtypes(new NamedType(Sub1.class,"sub1"));
- objectMapper.registerSubtypes(new NamedType(Sub2.class,"sub2"));
用於序列化和反序列化的註解類
1、@JsonSerialize和@JsonDeserialize
作用於方法和字段上,通過 using(JsonSerializer)和using(JsonDeserializer)來指定序列化和反序列化的實現,通常我們在需要自定義序列化和反序列化時會用到,比如下面的例子中的日期轉換
- @Test
- public void jsonSerializeAndDeSerialize() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- testPOJO.setBirthday(new Date());
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- System.out.println(jsonStr);
- String jsonStr2 = "{\"name\":\"myName\",\"birthday\":\"2014-11-11 19:01:58\"}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);
- System.out.println(testPOJO2.toString());
- }
- public static class TestPOJO{
- private String name;
- @JsonSerialize(using = MyDateSerializer.class)
- @JsonDeserialize(using = MyDateDeserializer.class)
- private Date birthday;
- //getters、setters省略
- @Override
- public String toString() {
- return "TestPOJO{" +
- "name='" + name + '\'' +
- ", birthday=" + birthday +
- '}';
- }
- }
- private static class MyDateSerializer extends JsonSerializer<Date>{
- @Override
- public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
- DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- String dateStr = dateFormat.format(value);
- jgen.writeString(dateStr);
- }
- }
- private static class MyDateDeserializer extends JsonDeserializer<Date>{
- @Override
- public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
- String value = jp.getValueAsString();
- DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- try {
- return dateFormat.parse(value);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- return null;
- }
- }
也可以通過使用as(JsonSerializer)和as(JsonDeserializer)來實現多態類型轉換,上面我們有提到多態類型處理時可以使用@JsonTypeInfo實現,還有一種比較簡便的方式就是使用@JsonSerialize和@JsonDeserialize指定as的子類類型,注意這裏必須指定爲子類類型纔可以實現替換運行時的類型
- @Test
- public void jsonSerializeAndDeSerialize() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- Sub1 sub1 = new Sub1();
- sub1.setId(1);
- sub1.setName("sub1Name");
- Sub2 sub2 = new Sub2();
- sub2.setId(2);
- sub2.setAge(22);
- testPOJO.setSub1(sub1);
- testPOJO.setSub2(sub2);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- System.out.println(jsonStr);
- String jsonStr2 = "{\"name\":\"myName\",\"sub1\":{\"id\":1,\"name\":\"sub1Name\"},\"sub2\":{\"id\":2,\"age\":22}}";
- TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);
- System.out.println(testPOJO2.toString());
- }
- public static class TestPOJO{
- private String name;
- @JsonSerialize(as = Sub1.class)
- @JsonDeserialize(as = Sub1.class)
- private MyIn sub1;
- @JsonSerialize(as = Sub2.class)
- @JsonDeserialize(as = Sub2.class)
- private MyIn sub2;
- //getters、setters省略
- @Override
- public String toString() {
- return "TestPOJO{" +
- "name='" + name + '\'' +
- ", sub1=" + sub1 +
- ", sub2=" + sub2 +
- '}';
- }
- }
- public static class MyIn{
- private int id;
- //getters、setters省略
- }
- public static class Sub1 extends MyIn{
- private String name;
- //getters、setters省略
- @Override
- public String toString() {
- return "Sub1{" +
- "id=" + getId() +
- "name='" + name + '\'' +
- '}';
- }
- }
- public static class Sub2 extends MyIn{
- private int age;
- //getters、setters省略
- @Override
- public String toString() {
- return "Sub1{" +
- "id=" + getId() +
- "age='" + age +
- '}';
- }
- }
最後@JsonSerialize可以配置include屬性來指定序列化時被註解的屬性被包含的方式,默認總是被包含進來,但是可以過濾掉空的屬性或有默認值的屬性,舉個簡單的過濾空屬性的例子如下
- @Test
- public void jsonSerializeAndDeSerialize() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("");
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{}",jsonStr);
- }
- public static class TestPOJO{
- @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
- private String name;
- //getters、setters省略
- }
2、@JsonPropertyOrder
作用在類上,被用來指明當序列化時需要對屬性做排序,它有2個屬性
一個是alphabetic:布爾類型,表示是否採用字母拼音順序排序,默認是爲false,即不排序
- @Test
- public void jsonPropertyOrder() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\",\"d\":\"4\",\"b\":\"2\"}",jsonStr);
- }
- public static class TestPOJO{
- private String a;
- private String c;
- private String d;
- private String b;
- //getters、setters省略
- }
還有一個屬性是value:數組類型,表示將優先其他屬性排序的屬性名稱
- @Test
- public void jsonPropertyOrder() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- System.out.println(jsonStr);
- Assert.assertEquals("{\"c\":\"3\",\"b\":\"2\",\"a\":\"1\",\"d\":\"4\"}",jsonStr);
- }
- @JsonPropertyOrder(alphabetic = true,value = {"c","b"})
- public static class TestPOJO{
- private String a;
- private String c;
- private String d;
- private String b;
- //getters、setters省略
- }
還記得本文上面最開始配置MapperFeature時也有屬性排序麼,對,就是
- objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);
3、@JsonView
視圖模板,作用於方法和屬性上,用來指定哪些屬性可以被包含在JSON視圖中,在前面我們知道已經有@JsonIgnore和@JsonIgnoreProperties可以排除過濾掉不需要序列化的屬性,可是如果一個POJO中有上百個屬性,比如訂單類、商品詳情類這種屬性超多,而我們可能只需要概要簡單信息即序列化時只想輸出其中幾個或10幾個屬性,此時使用@JsonIgnore和@JsonIgnoreProperties就顯得非常繁瑣,而使用@JsonView便會非常方便,只許在你想要輸出的屬性(或對應的getter)上添加@JsonView即可,舉例:
- @Test
- public void jsonView() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
- String jsonStr = objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO);
- Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\"}",jsonStr);
- String jsonStr2 = objectMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO);
- Assert.assertEquals("{\"d\":\"4\",\"b\":\"2\"}",jsonStr2);
- }
- public static class TestPOJO{
- @JsonView(FilterView.OutputA.class)
- private String a;
- @JsonView(FilterView.OutputA.class)
- private String c;
- @JsonView(FilterView.OutputB.class)
- private String d;
- @JsonView(FilterView.OutputB.class)
- private String b;
- //getters、setters忽略
- }
- private static class FilterView {
- static class OutputA {}
- static class OutputB {}
- }
4、@JsonFilter
Json屬性過濾器,作用於類,作用同上面的@JsonView,都是過濾掉不想要的屬性,輸出自己想要的屬性。和@FilterView不同的是@JsonFilter可以動態的過濾屬性,比如我不想輸出以system開頭的所有屬性等待,應該說@JsonFilter更高級一點,舉個簡單的例子
- @Test
- public void jsonFilter() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));
- objectMapper.setFilters(filters);
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"a\":\"1\"}",jsonStr);
- }
- @JsonFilter("myFilter")
- public static class TestPOJO{
- private String a;
- private String c;
- private String d;
- private String b;
- //getters、setters省略
- }
有時候我們可能需要根據現有的POJO來過濾屬性,而這種情況下通常不會讓你修改已有的代碼在POJO上加註解,這種情況下我們就可以結合@JsonFilter和MixInAnnotations來實現過濾屬性,如下例所示,不再多做解釋
- @Test
- public void jsonFilter() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setA("1");
- testPOJO.setB("2");
- testPOJO.setC("3");
- testPOJO.setD("4");
- ObjectMapper objectMapper = new ObjectMapper();
- FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));
- objectMapper.setFilters(filters);
- objectMapper.addMixInAnnotations(TestPOJO.class,MyFilterMixIn.class);
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- Assert.assertEquals("{\"a\":\"1\"}",jsonStr);
- }
- public static class TestPOJO{
- private String a;
- private String c;
- private String d;
- private String b;
- //getters、setters省略
- }
- @JsonFilter("myFilter")
- private static interface MyFilterMixIn{
- }
5、@JsonIgnoreType
作用於類,表示被註解該類型的屬性將不會被序列化和反序列化,也跟上面幾個一樣屬於過濾屬性功能的註解,舉例:
- @Test
- public void jsonFilter() throws Exception {
- TestPOJO testPOJO = new TestPOJO();
- testPOJO.setName("myName");
- Sub1 sub1 = new Sub1();
- sub1.setId(1);
- sub1.setName("sub1");
- Sub2 sub2 = new Sub2();
- sub2.setId(2);
- sub2.setAge(22);
- testPOJO.setMyIn(sub1);
- testPOJO.setSub1(sub1);
- testPOJO.setSub2(sub2);
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = objectMapper.writeValueAsString(testPOJO);
- System.out.println(jsonStr);
- }
- public static class TestPOJO{
- private Sub1 sub1;
- private Sub2 sub2;
- private MyIn myIn;
- private String name;
- //getters、setters省略
- }
- public static class MyIn{
- private int id;
- //getters、setters省略
- }
- @JsonIgnoreType
- public static class Sub1 extends MyIn{
- private String name;
- //getters、setters省略
- }
- @JsonIgnoreType
- public static class Sub2 extends MyIn{
- private int age;
- //getters、setters省略
- }
6、@JsonAnySetter
作用於方法,在反序列化時用來處理遇到未知的屬性的時候調用,在本文前面我們知道可以通過註解@JsonIgnoreProperties(ignoreUnknown=true)來過濾未知的屬性,但是如果需要這些未知的屬性該如何是好?那麼@JsonAnySetter就可以派上用場了,它通常會和map屬性配合使用用來保存未知的屬性,舉例:
- @Test
- public void jsonAnySetter() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"name\":\"myName\",\"code\":\"12345\",\"age\":12}";
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("myName",testPOJO.getName());
- Assert.assertEquals("12345",testPOJO.getOther().get("code"));
- Assert.assertEquals(12,testPOJO.getOther().get("age"));
- }
- public static class TestPOJO{
- private String name;
- private Map other = new HashMap();
- @JsonAnySetter
- public void set(String name,Object value) {
- other.put(name,value);
- }
- //getters、setters省略
- }
7、@JsonCreator
作用於方法,通常用來標註構造方法或靜態工廠方法上,使用該方法來構建實例,默認的是使用無參的構造方法,通常是和@JsonProperty或@JacksonInject配合使用,舉例
- @Test
- public void jsonCreator() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"full_name\":\"myName\",\"age\":12}";
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("myName",testPOJO.getName());
- Assert.assertEquals(12, testPOJO.getAge());
- }
- public static class TestPOJO{
- private String name;
- private int age;
- @JsonCreator
- public TestPOJO(@JsonProperty("full_name") String name,@JsonProperty("age") int age){
- this.name = name;
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public int getAge() {
- return age;
- }
- }
- @Test
- public void jsonCreator() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"name\":\"myName\",\"birthday\":1416299461556}";
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("myName",testPOJO.getName());
- System.out.println(testPOJO.getBirthday());
- }
- public static class TestPOJO{
- private String name;
- private Date birthday;
- private TestPOJO(String name,Date birthday){
- this.name = name;
- this.birthday = birthday;
- }
- @JsonCreator
- public static TestPOJO getInstance(@JsonProperty("name") String name,@JsonProperty("birthday") long timestamp){
- Date date = new Date(timestamp);
- return new TestPOJO(name,date);
- }
- public String getName() {
- return name;
- }
- public Date getBirthday() {
- return birthday;
- }
- }
除了這2種方式外,還有一種構造方式成爲授權式構造器,也是我們平常比較常用到的,這個構造器只有一個參數,且不能使用@JsonProperty。舉例:
- @Test
- public void jsonCreator() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"full_name\":\"myName\",\"age\":12}";
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("myName",testPOJO.getName());
- Assert.assertEquals(12,testPOJO.getAge());
- }
- public static class TestPOJO{
- private String name;
- private int age;
- @JsonCreator
- public TestPOJO(Map map){
- this.name = (String)map.get("full_name");
- this.age = (Integer)map.get("age");
- }
- public String getName() {
- return name;
- }
- public int getAge() {
- return age;
- }
- }
8、@JacksonInject
作用於屬性、方法、構造參數上,被用來反序列化時標記已經被注入的屬性,舉例:
- @Test
- public void jacksonInject() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"age\":12}";
- InjectableValues inject = new InjectableValues.Std().addValue("name","myName");
- TestPOJO testPOJO = objectMapper.reader(TestPOJO.class).with(inject).readValue(jsonStr);
- Assert.assertEquals("myName", testPOJO.getName());
- Assert.assertEquals(12,testPOJO.getAge());
- }
- public static class TestPOJO{
- @JacksonInject("name")
- private String name;
- private int age;
- //getters、setters省略
- }
9、@JsonPOJOBuilder
作用於類,用來標註如何定製構建對象,使用的是builder模式來構建,比如Value v = new ValueBuilder().withX(3).withY(4).build();這種就是builder模式來構建對象,通常會喝@JsonDeserialize.builder來配合使用,我們舉個例子:
- @Test
- public void jacksonInject() throws Exception {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonStr = "{\"name\":\"myName\",\"age\":12}";
- TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);
- Assert.assertEquals("myName", testPOJO.getName());
- Assert.assertEquals(12,testPOJO.getAge());
- }
- @JsonDeserialize(builder=TestPOJOBuilder.class)
- public static class TestPOJO{
- private String name;
- private int age;
- public TestPOJO(String name, int age) {
- this.name = name;
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public int getAge() {
- return age;
- }
- }
- @JsonPOJOBuilder(buildMethodName = "create",withPrefix = "with")
- public static class TestPOJOBuilder{
- private String name;
- private int age;
- public TestPOJOBuilder withName(String name) {
- this.name = name;
- return this;
- }
- public TestPOJOBuilder withAge(int age) {
- this.age = age;
- return this;
- }
- public TestPOJO create() {
- return new TestPOJO(name,age);
- }
- }
還有一些過期不推薦使用的註解,我們一筆帶過,主要知道他們是跟哪些其他註解功能一樣即可
作用於方法,1.0版本開始的註解,已經過期,不推薦使用,改用@JsonProperty
@JsonUseSerializer
作用於類和方法,1.5版本開始被移除了,改用@JsonSerialize
@JsonSetter
作用於方法,1.0版本開始的註解,已過期,不推薦使用,改用@JsonProperty
作用於方法和類,1.9版本開始被移除了,改爲@JsonDeserialize.as
作用於方法,1.9版本開始被移除了,改爲@JsonDeserialize.contentAs
作用於方法和類,1.9版本開始被移除了,改爲@JsonDeserialize.keyAs
作用於方法和類,1.5版本開始被移除了,改爲@JsonDeserialize