jackson annotations注解詳解

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

官方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

舉例:

?

[java]?view plain?copy
  1. public?static?class?TestPOJO{??
  2. ????TestPOJO(){}??
  3. ??????
  4. ????TestPOJO(String?name){??
  5. ????????this.name?=?name;??
  6. ????}??
  7. ????private?String?name;??
  8. ??
  9. ????@Override??
  10. ????public?String?toString()?{??
  11. ????????return?"TestPOJO{"?+??
  12. ????????????????????????"name='"?+?name?+?'\''?+??
  13. ????????????????????????'}';??
  14. ????}??
  15. }??

這個類我們只有一個private的name屬性,并且沒有提供對應的get,set方法,如果按照默認的屬性發現規則我們將無法序列化和反序列化name字段(如果沒有get,set方法,只有被public修飾的屬性才會被發現),你可以通過修改@JsonAutoDetect的fieldVisibility來調整自動發現級別,為了使name被自動發現,我們需要將級別調整為ANY

?

?

[java]?view plain?copy
  1. @JsonAutoDetect(fieldVisibility?=?JsonAutoDetect.Visibility.ANY)??

同理,除了fieldVisibility可以設置外,還可以設置getterVisibility、setterVisibility、isGetterVisibility、creatorVisibility級別,不再多講

?

?

?

?

除了上面的方式,你還可以有一些其他方式可以配置methods,fields和creators(構造器和靜態方法)的自動檢測,例如:

你可以配置MapperFeature來啟動/禁止一些特別類型(getters,setters,fields,creators)的自動檢測

比如下面的MapperFeature配置:

SORT_PROPERTIES_ALPHABETICALLY:按字母順序排序屬性

[java]?view plain?copy
  1. ObjectMapper?objectMapper?=?new?ObjectMapper();??
  2. objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);??

?

配置SerializationFeature

?

?

一些我們比較常用的SerializationFeature配置:

SerializationFeature.WRAP_ROOT_VALUE:是否環繞根元素,默認false,如果為true,則默認以類名作為根元素,你也可以通過@JsonRootName來自定義根元素名稱

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);??

?

舉例:

?

[java]?view plain?copy
  1. @JsonRootName("myPojo")??
  2. public?static?class?TestPOJO{??
  3. ????private?String?name;??
  4. ??
  5. ????public?String?getName()?{??
  6. ????????return?name;??
  7. ????}??
  8. ??
  9. ????public?void?setName(String?name)?{??
  10. ????????this.name?=?name;??
  11. ????}??
  12. }??

該類在序列化成json后類似如下:{"myPojo":{"name":"aaaa"}}

?

SerializationFeature.INDENT_OUTPUT:是否縮放排列輸出,默認false,有些場合為了便于排版閱讀則需要對輸出做縮放排列

?

[java]?view plain?copy
  1. 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

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true);??

比如如果一個類中有private Date date;這種日期屬性,序列化后為:{"date" : 1413800730456},若不為true,則為{"date" : "2014-10-20T10:26:06.604+0000"}

?

SerializationFeature.WRITE_ENUMS_USING_TO_STRING:序列化枚舉是以toString()來輸出,默認false,即默認以name()來輸出

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);??

?

SerializationFeature.WRITE_ENUMS_USING_INDEX:序列化枚舉是以ordinal()來輸出,默認false

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,true);??

?

舉例:

?

[java]?view plain?copy
  1. @Test??
  2. public?void?enumTest()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????testPOJO.setMyEnum(TestEnum.ENUM01);??
  6. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  7. ????objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,false);??
  8. ????objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false);??
  9. ????String?jsonStr1?=?objectMapper.writeValueAsString(testPOJO);??
  10. ????Assert.assertEquals("{\"myEnum\":\"ENUM01\",\"name\":\"myName\"}",jsonStr1);??
  11. ??
  12. ????ObjectMapper?objectMapper2?=?new?ObjectMapper();??
  13. ????objectMapper2.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);??
  14. ????String?jsonStr2?=?objectMapper2.writeValueAsString(testPOJO);??
  15. ????Assert.assertEquals("{\"myEnum\":\"enum_01\",\"name\":\"myName\"}",jsonStr2);??
  16. ??
  17. ????ObjectMapper?objectMapper3?=?new?ObjectMapper();??
  18. ????objectMapper3.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,true);??
  19. ????String?jsonStr3?=?objectMapper3.writeValueAsString(testPOJO);??
  20. ????Assert.assertEquals("{\"myEnum\":0,\"name\":\"myName\"}",jsonStr3);??
  21. }??
  22. public?static?class?TestPOJO{??
  23. ????TestPOJO(){}??
  24. ????private?TestEnum?myEnum;??
  25. ????private?String?name;??
  26. ??
  27. ????//getters、setters省略??
  28. }??
  29. ??
  30. public?static?enum?TestEnum{??
  31. ????ENUM01("enum_01"),ENUM02("enum_01"),ENUM03("enum_01");??
  32. ??
  33. ????private?String?title;??
  34. ??
  35. ????TestEnum(String?title)?{??
  36. ????????this.title?=?title;??
  37. ????}??
  38. ??
  39. ????@Override??
  40. ????public?String?toString()?{??
  41. ????????return?title;??
  42. ????}??
  43. }??

?

?

?

SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED:序列化單元素數組時不以數組來輸出,默認false

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);??

舉例:

?

[java]?view plain?copy
  1. @Test??
  2. public?void?singleElemArraysUnwrap()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????List<Integer>?counts?=?new?ArrayList<>();??
  6. ????counts.add(1);??
  7. ????testPOJO.setCounts(counts);??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????objectMapper.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,false);??
  10. ????String?jsonStr1?=?objectMapper.writeValueAsString(testPOJO);??
  11. ????Assert.assertEquals("{\"name\":\"myName\",\"counts\":[1]}",jsonStr1);??
  12. ??
  13. ????ObjectMapper?objectMapper2?=?new?ObjectMapper();??
  14. ????objectMapper2.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,true);??
  15. ????String?jsonStr2?=?objectMapper2.writeValueAsString(testPOJO);??
  16. ????Assert.assertEquals("{\"name\":\"myName\",\"counts\":1}",jsonStr2);??
  17. }??
  18. ??
  19. public?static?class?TestPOJO{??
  20. ????private?String?name;??
  21. ????private?List<Integer>?counts;??
  22. ??
  23. ????//getters、setters省略??
  24. }??

?

?

?

SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS:序列化Map時對key進行排序操作,默認false

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);??

舉例:

?

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?orderMapBykey()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????Map<String,Integer>?counts?=?new?HashMap<>();??
  6. ????counts.put("a",1);??
  7. ????counts.put("d",4);??
  8. ????counts.put("c",3);??
  9. ????counts.put("b",2);??
  10. ????counts.put("e",5);??
  11. ????testPOJO.setCounts(counts);??
  12. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  13. ????objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,false);??
  14. ????String?jsonStr1?=?objectMapper.writeValueAsString(testPOJO);??
  15. ????Assert.assertEquals("{\"name\":\"myName\",\"counts\":{\"d\":4,\"e\":5,\"b\":2,\"c\":3,\"a\":1}}",jsonStr1);??
  16. ??
  17. ????ObjectMapper?objectMapper2?=?new?ObjectMapper();??
  18. ????objectMapper2.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);??
  19. ????String?jsonStr2?=?objectMapper2.writeValueAsString(testPOJO);??
  20. ????Assert.assertEquals("{\"name\":\"myName\",\"counts\":{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}}",jsonStr2);??
  21. }??
  22. ??
  23. public?static?class?TestPOJO{??
  24. ????private?String?name;??
  25. ????private?Map<String,Integer>?counts;??
  26. ??
  27. ????//getters、setters省略??
  28. }??

?

?

?

SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS:序列化char[]時以json數組輸出,默認false

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);??

舉例:

?

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?charArraysAsJsonArrays()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????char[]?counts?=?new?char[]{'a','b','c','d'};??
  6. ????testPOJO.setCounts(counts);??
  7. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  8. ????objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,false);??
  9. ????String?jsonStr1?=?objectMapper.writeValueAsString(testPOJO);??
  10. ????Assert.assertEquals("{\"name\":\"myName\",\"counts\":\"abcd\"}",jsonStr1);??
  11. ??
  12. ????ObjectMapper?objectMapper2?=?new?ObjectMapper();??
  13. ????objectMapper2.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);??
  14. ????String?jsonStr2?=?objectMapper2.writeValueAsString(testPOJO);??
  15. ????Assert.assertEquals("{\"name\":\"myName\",\"counts\":[\"a\",\"b\",\"c\",\"d\"]}",jsonStr2);??
  16. }??
  17. ??
  18. public?static?class?TestPOJO{??
  19. ????private?String?name;??
  20. ????private?char[]?counts;??
  21. ??
  22. ????//getters、setters省略??
  23. }??

?

?

?

SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN:序列化BigDecimal時之間輸出原始數字還是科學計數,默認false,即是否以toPlainString()科學計數方式來輸出

?

[java]?view plain?copy
  1. objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);??

舉例:

?

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?bigDecimalAsPlain()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????testPOJO.setCount(new?BigDecimal("1e20"));??
  6. ??
  7. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  8. ????objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,false);??
  9. ????String?jsonStr1?=?objectMapper.writeValueAsString(testPOJO);??
  10. ????Assert.assertEquals("{\"name\":\"myName\",\"count\":1E+20}",jsonStr1);??
  11. ??
  12. ????ObjectMapper?objectMapper2?=?new?ObjectMapper();??
  13. ????objectMapper2.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,true);??
  14. ????String?jsonStr2?=?objectMapper2.writeValueAsString(testPOJO);??
  15. ????Assert.assertEquals("{\"name\":\"myName\",\"count\":100000000000000000000}",jsonStr2);??
  16. }??

更多的序列化配置參見點擊打開鏈接

?

配置DeserializationFeature

反序列化的配置這里不再多做解釋,參見點擊打開鏈接

需要注意的是對于第二種通過配置SerializationConfig和DeserializationConfig方式只能啟動/禁止自動檢測,無法修改我們所需的可見級別

有時候對每個實例進行可見級別的注解可能會非常麻煩,這時候我們需要配置一個全局的可見級別,通過objectMapper.setVisibilityChecker()來實現,默認的VisibilityChecker實現類為VisibilityChecker.Std,這樣可以滿足實現復雜場景下的基礎配置。

也有一些實用簡單的可見級別配置,比如:

?

[java]?view plain?copy
  1. ObjectMapper?objectMapper?=?new?ObjectMapper();??
  2. objectMapper.setVisibility(PropertyAccessor.FIELD,?JsonAutoDetect.Visibility.ANY)?//?auto-detect?all?member?fields??
  3. ????????????????.setVisibility(PropertyAccessor.GETTER,?JsonAutoDetect.Visibility.NONE)?//?but?only?public?getters??
  4. ????????????????.setVisibility(PropertyAccessor.IS_GETTER,?JsonAutoDetect.Visibility.NONE)?//?and?none?of?"is-setters"??
  5. ;??

你也可以通過下面方式來禁止所有的自動檢測功能

?

[java]?view plain?copy
  1. ObjectMapper?objectMapper?=?new?ObjectMapper();??
  2. objectMapper.setVisibilityChecker(objectMapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));??

?

?

jackson的常用注解

?

?

1、@JsonAutoDetect

看上面自動檢測,不再重復

2、@JsonIgnore

作用在字段或方法上,用來完全忽略被注解的字段和方法對應的屬性,即便這個字段或方法可以被自動檢測到或者還有其他的注解

舉例

?

[java]?view plain?copy
  1. ???????@Test??
  2. public?void?jsonIgnoreTest()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setId(111);??
  5. ????testPOJO.setName("myName");??
  6. ????testPOJO.setCount(22);??
  7. ??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  10. ????Assert.assertEquals("{\"id\":111}",jsonStr);??
  11. ??
  12. ????String?jsonStr2?=?"{\"id\":111,\"name\":\"myName\",\"count\":22}";??
  13. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,?TestPOJO.class);??
  14. ????Assert.assertEquals(111,testPOJO2.getId());??
  15. ????Assert.assertNull(testPOJO2.getName());??
  16. ????Assert.assertEquals(0,testPOJO2.getCount());??
  17. }??
  18. ??
  19. public?static?class?TestPOJO{??
  20. ????private?int?id;??
  21. ????@JsonIgnore??
  22. ????private?String?name;??
  23. ????private?int?count;??
  24. ??
  25. ????public?int?getId()?{??
  26. ????????return?id;??
  27. ????}??
  28. ??
  29. ????public?void?setId(int?id)?{??
  30. ????????this.id?=?id;??
  31. ????}??
  32. ??
  33. ????public?String?getName()?{??
  34. ????????return?name;??
  35. ????}??
  36. ??
  37. ????public?void?setName(String?name)?{??
  38. ????????this.name?=?name;??
  39. ????}??
  40. ??
  41. ????public?int?getCount()?{??
  42. ????????return?count;??
  43. ????}??
  44. ????@JsonIgnore??
  45. ????public?void?setCount(int?count)?{??
  46. ????????this.count?=?count;??
  47. ????}??
  48. }??

當@JsonIgnore不管注解在getters上還是setters上都會忽略對應的屬性

?

3、@JsonProperty

?

?

作用在字段或方法上,用來對屬性的序列化/反序列化,可以用來避免遺漏屬性,同時提供對屬性名稱重命名,比如在很多場景下Java對象的屬性是按照規范的駝峰書寫,但是實際展示的卻是類似C-style或C++/Microsolft style

舉例

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonPropertyTest()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.wahaha(111);??
  5. ????testPOJO.setFirstName("myName");??
  6. ??
  7. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  8. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  9. ????Assert.assertEquals("{\"id\":111,\"first_name\":\"myName\"}",jsonStr);??
  10. ??
  11. ????String?jsonStr2?=?"{\"id\":111,\"first_name\":\"myName\"}";??
  12. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,?TestPOJO.class);??
  13. ????Assert.assertEquals(111,?testPOJO2.wahaha());??
  14. ????Assert.assertEquals("myName",?testPOJO2.getFirstName());??
  15. }??
  16. ??
  17. public?static?class?TestPOJO{??
  18. ????@JsonProperty//注意這里必須得有該注解,因為沒有提供對應的getId和setId函數,而是其他的getter和setter,防止遺漏該屬性??
  19. ????private?int?id;??
  20. ????@JsonProperty("first_name")??
  21. ????private?String?firstName;??
  22. ??
  23. ????public?int?wahaha()?{??
  24. ????????return?id;??
  25. ????}??
  26. ??
  27. ????public?void?wahaha(int?id)?{??
  28. ????????this.id?=?id;??
  29. ????}??
  30. ??
  31. ????public?String?getFirstName()?{??
  32. ????????return?firstName;??
  33. ????}??
  34. ??
  35. ????public?void?setFirstName(String?firstName)?{??
  36. ????????this.firstName?=?firstName;??
  37. ????}??
  38. }??

4、@JsonIgnoreProperties

?

作用在類上,用來說明有些屬性在序列化/反序列化時需要忽略掉,可以將它看做是@JsonIgnore的批量操作,但它的功能比@JsonIgnore要強,比如一個類是代理類,我們無法將將@JsonIgnore標記在屬性或方法上,此時便可用@JsonIgnoreProperties標注在類聲明上,它還有一個重要的功能是作用在反序列化時解析字段時過濾一些未知的屬性,否則通常情況下解析到我們定義的類不認識的屬性便會拋出異常。

可以注明是想要忽略的屬性列表如@JsonIgnoreProperties({"name","age","title"}),

也可以注明過濾掉未知的屬性如@JsonIgnoreProperties(ignoreUnknown=true)

舉例:

?

[java]?view plain?copy
  1. @Test(expected?=?UnrecognizedPropertyException.class)??
  2. public?void?JsonIgnoreProperties()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setId(111);??
  5. ????testPOJO.setName("myName");??
  6. ????testPOJO.setAge(22);??
  7. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  8. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  9. ????Assert.assertEquals("{\"id\":111}",jsonStr);//name和age被忽略掉了??
  10. ??
  11. ????String?jsonStr2?=?"{\"id\":111,\"name\":\"myName\",\"age\":22,\"title\":\"myTitle\"}";??
  12. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,?TestPOJO.class);??
  13. ????Assert.assertEquals(111,?testPOJO2.getId());??
  14. ????Assert.assertNull(testPOJO2.getName());??
  15. ????Assert.assertEquals(0,testPOJO2.getAge());??
  16. ????String?jsonStr3?=?"{\"id\":111,\"name\":\"myName\",\"count\":33}";//這里有個未知的count屬性,反序列化會報錯??
  17. ????objectMapper.readValue(jsonStr3,?TestPOJO.class);??
  18. }??
  19. ??
  20. @JsonIgnoreProperties({"name","age","title"})??
  21. public?static?class?TestPOJO{??
  22. ????private?int?id;??
  23. ????private?String?name;??
  24. ????private?int?age;??
  25. ??
  26. ????//getters、setters省略??
  27. }??

如果將上面的

[java]?view plain?copy
  1. @JsonIgnoreProperties({"name","age","title"})??

?

更換為

[java]?view plain?copy
  1. @JsonIgnoreProperties(ignoreUnknown=true)??

那么測試用例中在反序列化未知的count屬性時便不會拋出異常了

?

?

?

?

?

5、@JsonUnwrapped

作用在屬性字段或方法上,用來將子JSON對象的屬性添加到封閉的JSON對象,說起來比較難懂,看個例子就很清楚了,不多解釋

舉例

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonUnwrapped()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setId(111);??
  5. ????TestName?testName?=?new?TestName();??
  6. ????testName.setFirstName("張");??
  7. ????testName.setSecondName("三");??
  8. ????testPOJO.setName(testName);??
  9. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  10. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  11. ????//如果沒有@JsonUnwrapped,序列化后將為{"id":111,"name":{"firstName":"張","secondName":"三"}}??
  12. ????//因為在name屬性上加了@JsonUnwrapped,所以name的子屬性firstName和secondName將不會包含在name中。??
  13. ????Assert.assertEquals("{\"id\":111,\"firstName\":\"張\",\"secondName\":\"三\"}",jsonStr);??
  14. ????String?jsonStr2?=?"{\"id\":111,\"firstName\":\"張\",\"secondName\":\"三\"}";??
  15. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,TestPOJO.class);??
  16. ????Assert.assertEquals(111,testPOJO2.getId());??
  17. ????Assert.assertEquals("張",testPOJO2.getName().getFirstName());??
  18. ????Assert.assertEquals("三",testPOJO2.getName().getSecondName());??
  19. }??
  20. ??
  21. public?static?class?TestPOJO{??
  22. ????private?int?id;??
  23. ????@JsonUnwrapped??
  24. ????private?TestName?name;??
  25. ??
  26. ????//getters、setters省略??
  27. }?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????public?static?class?TestName{??
  28. ????private?String?firstName;??
  29. ????private?String?secondName;??
  30. ??
  31. ????//getters、setters省略??
  32. }??

在2.0+版本中@JsonUnwrapped添加了prefix和suffix屬性,用來對字段添加前后綴,這在有關屬性分組上比較有用,在上面的測試用例中,如果我們將TestPOJO的name屬性上的@JsonUnwrapped添加前后綴配置,即

[java]?view plain?copy
  1. @JsonUnwrapped(prefix?=?"name_",suffix?=?"_test")??

那么TestPOJO序列化后將為{"id":111,"name_firstName_test":"張","name_secondName_test":"三"},反序列化時也要加上前后綴才會被解析為POJO

?

6、@JsonIdentityInfo

2.0+版本新注解,作用于類或屬性上,被用來在序列化/反序列化時為該對象或字段添加一個對象識別碼,通常是用來解決循環嵌套的問題,比如數據庫中的多對多關系,通過配置屬性generator來確定識別碼生成的方式,有簡單的,配置屬性property來確定識別碼的名稱,識別碼名稱沒有限制。
對象識別碼可以是虛擬的,即存在在JSON中,但不是POJO的一部分,這種情況下我們可以如此使用注解

?

[java]?view plain?copy
  1. @JsonIdentityInfo(generator?=?ObjectIdGenerators.IntSequenceGenerator.class,property?=?"@id")??


對象識別碼也可以是真實存在的,即以對象的屬性為識別碼,通常這種情況下我們一般以id屬性為識別碼,可以這么使用注解

?

?

[java]?view plain?copy
  1. @JsonIdentityInfo(generator?=?ObjectIdGenerators.PropertyGenerator.class,property?=?"id")??

舉例

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonIdentityInfo()?throws?Exception?{??
  3. ????Parent?parent?=?new?Parent();??
  4. ????parent.setName("jack");??
  5. ????Child?child?=?new?Child();??
  6. ????child.setName("mike");??
  7. ????Child[]?children?=?new?Child[]{child};??
  8. ????parent.setChildren(children);??
  9. ????child.setParent(parent);??
  10. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  11. ????String?jsonStr?=?objectMapper.writeValueAsString(parent);??
  12. ????Assert.assertEquals("{\"@id\":1,\"name\":\"jack\",\"children\":[{\"name\":\"mike\",\"parent\":1}]}",jsonStr);??
  13. }??
  14. ??
  15. @JsonIdentityInfo(generator?=?ObjectIdGenerators.IntSequenceGenerator.class,property?=?"@id")??
  16. public?static?class?Parent{??
  17. ????private?String?name;??
  18. ????private?Child[]?children;??
  19. ??
  20. ????//getters、setters省略??
  21. }??
  22. ??
  23. public?static?class?Child{??
  24. ????private?String?name;??
  25. ????private?Parent?parent;??
  26. ??
  27. ????//getters、setters省略??
  28. }??

?

這里需要提醒一下的是在1.6版本中提供了@JsonManagedReference和@JsonBackReference來解決循環嵌套問題,因為屬于過時注解這里就不解釋了,有興趣的可以自己看

7、@JsonNaming

jackson 2.1+版本的注解,作用于類或方法,注意這個注解是在jackson-databind包中而不是在jackson-annotations包里,它可以讓你定制屬性命名策略,作用和前面提到的@JsonProperty的重命名屬性名稱相同。比如
你有一個JSON串{"in_reply_to_user_id":"abc123"},需要反序列化為POJO,POJO一般情況下則需要如此寫

?

[java]?view plain?copy
  1. public?static?class?TestPOJO{??
  2. ??
  3. ????private?String?in_reply_to_user_id;??
  4. ??
  5. ????public?String?getIn_reply_to_user_id()?{??
  6. ????????return?in_reply_to_user_id;??
  7. ????}??
  8. ??
  9. ????public?void?setIn_reply_to_user_id(String?in_reply_to_user_id)?{??
  10. ????????this.in_reply_to_user_id?=?in_reply_to_user_id;??
  11. ????}??
  12. }??

但這顯然不符合JAVA的編碼規范,你可以用@JsonProperty,比如:

?

?

[java]?view plain?copy
  1. public?static?class?TestPOJO{??
  2. ??
  3. ????@JsonProperty("in_reply_to_user_id")??
  4. ????private?String?inReplyToUserId;??
  5. ??
  6. ????public?String?getInReplyToUserId()?{??
  7. ????????return?inReplyToUserId;??
  8. ????}??
  9. ??
  10. ????public?void?setInReplyToUserId(String?inReplyToUserId)?{??
  11. ????????this.inReplyToUserId?=?inReplyToUserId;??
  12. ????}??
  13. }??

這樣就符合規范了,可是如果POJO里有很多屬性,給每個屬性都要加上@JsonProperty是多么繁重的工作,這里就需要用到@JsonNaming了,它不僅能制定統一的命名規則,還能任意按自己想要的方式定制

?

舉例

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonNaming()?throws?Exception{??
  3. ????String?jsonStr?=?"{\"in_reply_to_user_id\":\"abc123\"}";??
  4. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("abc123",testPOJO.getInReplyToUserId());??
  7. ??
  8. ????TestPOJO?testPOJO2?=?new?TestPOJO();??
  9. ????testPOJO2.setInReplyToUserId("abc123");??
  10. ????String?jsonStr2?=?objectMapper.writeValueAsString(testPOJO2);??
  11. ????Assert.assertEquals(jsonStr,jsonStr2);??
  12. }??
  13. ??
  14. @JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)??
  15. public?static?class?TestPOJO{??
  16. ??
  17. ????private?String?inReplyToUserId;??
  18. ??
  19. ????public?String?getInReplyToUserId()?{??
  20. ????????return?inReplyToUserId;??
  21. ????}??
  22. ??
  23. ????public?void?setInReplyToUserId(String?inReplyToUserId)?{??
  24. ????????this.inReplyToUserId?=?inReplyToUserId;??
  25. ????}??
  26. }??

@JsonNaming使用了jackson已經實現的PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy,它可以將大寫轉換為小寫并添加下劃線。你可以自定義,必須繼承類PropertyNamingStrategy,建議繼承PropertyNamingStrategyBase,我們自己實現一個類似LowerCaseWithUnderscoresStrategy的策略,只是將下劃線改為破折號

?

舉例

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonNaming()?throws?Exception{??
  3. ????String?jsonStr?=?"{\"in-reply-to-user-id\":\"abc123\"}";??
  4. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("abc123",?testPOJO.getInReplyToUserId());??
  7. ??
  8. ????TestPOJO?testPOJO2?=?new?TestPOJO();??
  9. ????testPOJO2.setInReplyToUserId("abc123");??
  10. ????String?jsonStr2?=?objectMapper.writeValueAsString(testPOJO2);??
  11. ????Assert.assertEquals(jsonStr,?jsonStr2);??
  12. }??
  13. ??
  14. @JsonNaming(MyPropertyNamingStrategy.class)??
  15. public?static?class?TestPOJO{??
  16. ??
  17. ????private?String?inReplyToUserId;??
  18. ??
  19. ????public?String?getInReplyToUserId()?{??
  20. ????????return?inReplyToUserId;??
  21. ????}??
  22. ??
  23. ????public?void?setInReplyToUserId(String?inReplyToUserId)?{??
  24. ????????this.inReplyToUserId?=?inReplyToUserId;??
  25. ????}??
  26. }??
  27. ??
  28. public?static?class?MyPropertyNamingStrategy?extends?PropertyNamingStrategy.PropertyNamingStrategyBase?{??
  29. ????@Override??
  30. ????public?String?translate(String?input)?{??
  31. ????????if?(input?==?null)?return?input;?//?garbage?in,?garbage?out??
  32. ????????int?length?=?input.length();??
  33. ????????StringBuilder?result?=?new?StringBuilder(length?*?2);??
  34. ????????int?resultLength?=?0;??
  35. ????????boolean?wasPrevTranslated?=?false;??
  36. ????????for?(int?i?=?0;?i?<?length;?i++)??
  37. ????????{??
  38. ????????????char?c?=?input.charAt(i);??
  39. ????????????if?(i?>?0?||?c?!=?'-')?//?skip?first?starting?underscore??
  40. ????????????{??
  41. ????????????????if?(Character.isUpperCase(c))??
  42. ????????????????{??
  43. ????????????????????if?(!wasPrevTranslated?&&?resultLength?>?0?&&?result.charAt(resultLength?-?1)?!=?'-')??
  44. ????????????????????{??
  45. ????????????????????????result.append('-');??
  46. ????????????????????????resultLength++;??
  47. ????????????????????}??
  48. ????????????????????c?=?Character.toLowerCase(c);??
  49. ????????????????????wasPrevTranslated?=?true;??
  50. ????????????????}??
  51. ????????????????else??
  52. ????????????????{??
  53. ????????????????????wasPrevTranslated?=?false;??
  54. ????????????????}??
  55. ????????????????result.append(c);??
  56. ????????????????resultLength++;??
  57. ????????????}??
  58. ????????}??
  59. ????????return?resultLength?>?0???result.toString()?:?input;??
  60. ????}??
  61. }??

如果你想讓自己定制的策略對所有解析都實現,除了對每個具體的實體類對應的位置加上@JsonNaming外你還可以如下做全局配置

?

?

[java]?view plain?copy
  1. ObjectMapper?objectMapper?=?new?ObjectMapper();??
  2. objectMapper.setPropertyNamingStrategy(new?MyPropertyNamingStrategy());??

?

多態類型處理

?

?

jackson允許配置多態類型處理,當進行反序列話時,JSON數據匹配的對象可能有多個子類型,為了正確的讀取對象的類型,我們需要添加一些類型信息。可以通過下面幾個注解來實現:

@JsonTypeInfo

作用于類/接口,被用來開啟多態類型處理,對基類/接口和子類/實現類都有效

?

[java]?view plain?copy
  1. @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在基類上使用,比如:

?

[java]?view plain?copy
  1. @JsonTypeInfo(use?=?JsonTypeInfo.Id.NAME,include?=?JsonTypeInfo.As.PROPERTY,property?=?"typeName")??
  2. @JsonSubTypes({@JsonSubTypes.Type(value=Sub1.class,name?=?"sub1"),@JsonSubTypes.Type(value=Sub2.class,name?=?"sub2")})??

@JsonSubTypes的值是一個@JsonSubTypes.Type[]數組,里面枚舉了多態類型(value對應類)和類型的標識符值(name對應@JsonTypeInfo中的property標識名稱的值,此為可選值,若不制定需由@JsonTypeName在子類上制定)

?

@JsonTypeName

作用于子類,用來為多態子類指定類型標識符的值

比如:

?

[java]?view plain?copy
  1. @JsonTypeName(value?=?"sub1")??

value屬性作用同上面@JsonSubTypes里的name作用

?

@JsonTypeResolver和@JsonTypeIdResoler

?

?

作用于類,可以自定義多態的類型標識符,這個平時很少用到,主要是現有的一般就已經滿足絕大多數的需求了,如果你需要比較特別的類型標識符,建議使用這2個注解,自己定制基于TypeResolverBuilder和TypeIdResolver的類即可

我們看幾個jackson處理多態的例子

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonTypeInfo()?throws?Exception{??
  3. ????Sub1?sub1?=?new?Sub1();??
  4. ????sub1.setId(1);??
  5. ????sub1.setName("sub1Name");??
  6. ????Sub2?sub2?=?new?Sub2();??
  7. ????sub2.setId(2);??
  8. ????sub2.setAge(33);??
  9. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  10. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  11. ????testPOJO.setMyIns(new?MyIn[]{sub1,?sub2});??
  12. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  13. ????Assert.assertEquals("{\"myIns\":[{\"id\":1,\"name\":\"sub1Name\"},{\"id\":2,\"age\":33}]}",?jsonStr);??
  14. ????System.out.println(jsonStr);??
  15. }??
  16. ??
  17. public?static?abstract?class?MyIn{??
  18. ????private?int?id;??
  19. ??
  20. ????//getters、setters省略??
  21. }??
  22. ??
  23. public?static?class?Sub1?extends?MyIn{??
  24. ????private?String?name;??
  25. ??
  26. ????//getters、setters省略??
  27. }??
  28. ??
  29. public?static?class?Sub2?extends?MyIn{??
  30. ????private?int?age;??
  31. ??
  32. ????//getters、setters省略??
  33. }??

這是序列化時最簡單的一種多態處理方式,因為沒有使用任何多態處理注解,即默認使用的識別碼類型為JsonTypeInfo.Id.NONE,而jackson沒有自動搜索功能,所以只能序列化而不能反序列化,上面序列化測試的結果為{"myIns":[{"id":1,"name":"sub1Name"},{"id":2,"age":33}]},我們可以看到JSON串中是沒有對應的多態類型識別碼的。

?

下面我們在基類MyIn上加上多態處理相關注解,首先我們在基類MyIn上添加@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)即

?

[java]?view plain?copy
  1. @JsonTypeInfo(use?=?JsonTypeInfo.Id.CLASS)??
  2. public?static?abstract?class?MyIn{??
  3. ????private?int?id;??
  4. ??
  5. ????//getters、setters省略??
  6. }??

執行上面的序列化測試代碼結果將會是

?

{"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")即

?

[java]?view plain?copy
  1. @JsonTypeInfo(use?=?JsonTypeInfo.Id.CLASS,property?=?"typeName")??
  2. public?static?abstract?class?MyIn{??
  3. ????private?int?id;??
  4. ??
  5. ????//getters、setters省略??
  6. }??

再次執行上面的序列化測試代碼結果將會是

?

{"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即

?

[java]?view plain?copy
  1. @JsonTypeInfo(use?=?JsonTypeInfo.Id.CLASS,include?=?JsonTypeInfo.As.WRAPPER_OBJECT,property?=?"typeName")??
  2. public?static?abstract?class?MyIn{??
  3. ????private?int?id;??
  4. ??
  5. ????//getters、setters省略??
  6. }??

再次執行序列化測試,結果為

?

{"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")

?

[java]?view plain?copy
  1. @JsonTypeInfo(use?=?JsonTypeInfo.Id.MINIMAL_CLASS,include?=?JsonTypeInfo.As.PROPERTY,property?=?"typeName")??
  2. public?static?abstract?class?MyIn{??
  3. ????private?int?id;??
  4. ??
  5. ????//getters、setters省略??
  6. }??

測試序列化結果為

?

{"myIns":[{"typeName":".JacksonUtilsTest$Sub1","id":1,"name":"sub1Name"},{"typeName":".JacksonUtilsTest$Sub2","id":2,"age":33}]}

發現已經沒有同包的package名稱,識別碼的值更加簡短了

測試反序列化

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonTypeInfo()?throws?Exception{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr2?=?"{\"myIns\":[{\"typeName\":\".JacksonUtilsTest$Sub1\",\"id\":1,\"name\":\"sub1Name\"},{\"typeName\":\".JacksonUtilsTest$Sub2\",\"id\":2,\"age\":33}]}";??
  5. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,TestPOJO.class);??
  6. ????MyIn[]?myIns?=?testPOJO2.getMyIns();??
  7. ????for?(MyIn?myIn?:?myIns)?{??
  8. ????????System.out.println(myIn.getClass().getSimpleName());??
  9. ????}??
  10. }??

結果將會顯示為Sub1和Sub2說明是可以實現多態的反序列化的

?

可能我們在反序列化時覺得如此傳遞識別碼很不友好,最好可以自定義識別碼的值,可以選擇use = JsonTypeInfo.Id.NAME和@JsonSubTypes配合即

?

[java]?view plain?copy
  1. @JsonTypeInfo(use?=?JsonTypeInfo.Id.NAME,include?=?JsonTypeInfo.As.PROPERTY,property?=?"typeName")??
  2. @JsonSubTypes({@JsonSubTypes.Type(value=Sub1.class,name="sub1"),@JsonSubTypes.Type(value=Sub2.class,name="sub2")})??
  3. public?static?abstract?class?MyIn{??
  4. ????private?int?id;??
  5. ????//getters、setters省略??
  6. }??

執行序列化結果為

?

{"myIns":[{"typeName":"sub1","id":1,"name":"sub1Name"},{"typeName":"sub2","id":2,"age":33}]}

使用這個結果反序列化也可以得到我們想要的結果,或者在子類上添加@JsonTypeName(value = "sub1")和@JsonTypeName(value = "sub2")以便取代@JsonSubTypes里的name

如果想不使用@JsonSubTypes來實現反序列化,我們可以在ObjectMapper上注冊子類實現,即

?

[java]?view plain?copy
  1. ObjectMapper?objectMapper?=?new?ObjectMapper();??
  2. objectMapper.registerSubtypes(new?NamedType(Sub1.class,"sub1"));??
  3. objectMapper.registerSubtypes(new?NamedType(Sub2.class,"sub2"));??

更多多態處理的例子還請大家自己研究

?

?

用于序列化和反序列化的注解類

1、@JsonSerialize和@JsonDeserialize

作用于方法和字段上,通過 using(JsonSerializer)和using(JsonDeserializer)來指定序列化和反序列化的實現,通常我們在需要自定義序列化和反序列化時會用到,比如下面的例子中的日期轉換

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonSerializeAndDeSerialize()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????testPOJO.setBirthday(new?Date());??
  6. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  7. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  8. ????System.out.println(jsonStr);??
  9. ??
  10. ????String?jsonStr2?=?"{\"name\":\"myName\",\"birthday\":\"2014-11-11?19:01:58\"}";??
  11. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,TestPOJO.class);??
  12. ????System.out.println(testPOJO2.toString());??
  13. }??
  14. ??
  15. public?static?class?TestPOJO{??
  16. ????private?String?name;??
  17. ????@JsonSerialize(using?=?MyDateSerializer.class)??
  18. ????@JsonDeserialize(using?=?MyDateDeserializer.class)??
  19. ????private?Date?birthday;??
  20. ??
  21. ????//getters、setters省略??
  22. ??
  23. ????@Override??
  24. ????public?String?toString()?{??
  25. ????????return?"TestPOJO{"?+??
  26. ????????????"name='"?+?name?+?'\''?+??
  27. ????????????",?birthday="?+?birthday?+??
  28. ????????????'}';??
  29. ????}??
  30. }??
  31. ??
  32. private?static?class?MyDateSerializer?extends?JsonSerializer<Date>{??
  33. ????@Override??
  34. ????public?void?serialize(Date?value,?JsonGenerator?jgen,?SerializerProvider?provider)?throws?IOException,?JsonProcessingException?{??
  35. ????????DateFormat?dateFormat?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");??
  36. ????????String?dateStr?=?dateFormat.format(value);??
  37. ????????jgen.writeString(dateStr);??
  38. ????}??
  39. }??
  40. ??
  41. private?static?class?MyDateDeserializer?extends?JsonDeserializer<Date>{??
  42. ????@Override??
  43. ????public?Date?deserialize(JsonParser?jp,?DeserializationContext?ctxt)?throws?IOException,?JsonProcessingException?{??
  44. ????????String?value?=?jp.getValueAsString();??
  45. ????????DateFormat?dateFormat?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");??
  46. ????????try?{??
  47. ????????????return?dateFormat.parse(value);??
  48. ????????}?catch?(ParseException?e)?{??
  49. ????????????e.printStackTrace();??
  50. ????????}??
  51. ????????return?null;??
  52. ????}??
  53. }??

上面的例子中自定義了日期的序列化和反序列化方式,可以將Date和指定日期格式字符串之間相互轉換。

也可以通過使用as(JsonSerializer)和as(JsonDeserializer)來實現多態類型轉換,上面我們有提到多態類型處理時可以使用@JsonTypeInfo實現,還有一種比較簡便的方式就是使用@JsonSerialize和@JsonDeserialize指定as的子類類型,注意這里必須指定為子類類型才可以實現替換運行時的類型

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonSerializeAndDeSerialize()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????Sub1?sub1?=?new?Sub1();??
  6. ????sub1.setId(1);??
  7. ????sub1.setName("sub1Name");??
  8. ????Sub2?sub2?=?new?Sub2();??
  9. ????sub2.setId(2);??
  10. ????sub2.setAge(22);??
  11. ????testPOJO.setSub1(sub1);??
  12. ????testPOJO.setSub2(sub2);??
  13. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  14. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  15. ????System.out.println(jsonStr);??
  16. ??
  17. ????String?jsonStr2?=?"{\"name\":\"myName\",\"sub1\":{\"id\":1,\"name\":\"sub1Name\"},\"sub2\":{\"id\":2,\"age\":22}}";??
  18. ????TestPOJO?testPOJO2?=?objectMapper.readValue(jsonStr2,TestPOJO.class);??
  19. ????System.out.println(testPOJO2.toString());??
  20. }??
  21. ??
  22. public?static?class?TestPOJO{??
  23. ????private?String?name;??
  24. ????@JsonSerialize(as?=?Sub1.class)??
  25. ????@JsonDeserialize(as?=?Sub1.class)??
  26. ????private?MyIn?sub1;??
  27. ????@JsonSerialize(as?=?Sub2.class)??
  28. ????@JsonDeserialize(as?=?Sub2.class)??
  29. ????private?MyIn?sub2;??
  30. ??
  31. ????//getters、setters省略??
  32. ??
  33. ????@Override??
  34. ????public?String?toString()?{??
  35. ????????return?"TestPOJO{"?+??
  36. ????????????"name='"?+?name?+?'\''?+??
  37. ????????????",?sub1="?+?sub1?+??
  38. ????????????",?sub2="?+?sub2?+??
  39. ????????????'}';??
  40. ????}??
  41. }??
  42. ??
  43. public?static?class?MyIn{??
  44. ????private?int?id;??
  45. ??
  46. ????//getters、setters省略??
  47. }??
  48. ??
  49. public?static?class?Sub1?extends?MyIn{??
  50. ????private?String?name;??
  51. ??
  52. ????//getters、setters省略??
  53. ??
  54. ????@Override??
  55. ????public?String?toString()?{??
  56. ????????return?"Sub1{"?+??
  57. ????????????"id="?+?getId()??+??
  58. ????????????"name='"?+?name?+?'\''?+??
  59. ????????????'}';??
  60. ????}??
  61. }??
  62. public?static?class?Sub2?extends?MyIn{??
  63. ????private?int?age;??
  64. ????//getters、setters省略??
  65. ??
  66. ????@Override??
  67. ????public?String?toString()?{??
  68. ????????return?"Sub1{"?+??
  69. ????????????"id="?+?getId()?+??
  70. ????????????"age='"?+?age?+??
  71. ????????????'}';??
  72. ????}??
  73. }??

上面例子中通過as來指定了需要替換實際運行時類型的子類,實際上上面例子中序列化時是可以不使用@JsonSerialize(as = Sub1.class)的,因為jackson可以自動將POJO轉換為對應的JSON,而反序列化時由于無法自動檢索匹配類型必須要指定@JsonDeserialize(as = Sub1.class)方可實現

?

?

最后@JsonSerialize可以配置include屬性來指定序列化時被注解的屬性被包含的方式,默認總是被包含進來,但是可以過濾掉空的屬性或有默認值的屬性,舉個簡單的過濾空屬性的例子如下

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonSerializeAndDeSerialize()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("");??
  5. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  6. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  7. ????Assert.assertEquals("{}",jsonStr);??
  8. }??
  9. ??
  10. public?static?class?TestPOJO{??
  11. ????@JsonSerialize(include?=?JsonSerialize.Inclusion.NON_EMPTY)??
  12. ????private?String?name;??
  13. ??
  14. ????//getters、setters省略??
  15. }??

2、@JsonPropertyOrder

作用在類上,被用來指明當序列化時需要對屬性做排序,它有2個屬性

?

一個是alphabetic:布爾類型,表示是否采用字母拼音順序排序,默認是為false,即不排序

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonPropertyOrder()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setA("1");??
  5. ????testPOJO.setB("2");??
  6. ????testPOJO.setC("3");??
  7. ????testPOJO.setD("4");??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  10. ????Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\",\"d\":\"4\",\"b\":\"2\"}",jsonStr);??
  11. }??
  12. ??
  13. public?static?class?TestPOJO{??
  14. ????private?String?a;??
  15. ????private?String?c;??
  16. ????private?String?d;??
  17. ????private?String?b;??
  18. ??
  19. ????//getters、setters省略??
  20. }??

我們先看一個默認的排序方式,序列化單元測試結果依次為{"a":"1","c":"3","d":"4","b":"2"},即是沒有經過排序操作的,在TestPOJO上加上@jsonPropertyOrder(alphabetic = true)再執行測試結果將會為{"a":"1","b":"2","c":"3","d":"4"}
還有一個屬性是value:數組類型,表示將優先其他屬性排序的屬性名稱

?

?

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonPropertyOrder()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setA("1");??
  5. ????testPOJO.setB("2");??
  6. ????testPOJO.setC("3");??
  7. ????testPOJO.setD("4");??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  10. ????System.out.println(jsonStr);??
  11. ????Assert.assertEquals("{\"c\":\"3\",\"b\":\"2\",\"a\":\"1\",\"d\":\"4\"}",jsonStr);??
  12. }??
  13. ??
  14. @JsonPropertyOrder(alphabetic?=?true,value?=?{"c","b"})??
  15. public?static?class?TestPOJO{??
  16. ????private?String?a;??
  17. ????private?String?c;??
  18. ????private?String?d;??
  19. ????private?String?b;??
  20. ??
  21. ????//getters、setters省略??
  22. }??

上面例子可以看到value指定了c和b屬性優先排序,所以序列化后為{"c":"3","b":"2","a":"1","d":"4"}

?

還記得本文上面最開始配置MapperFeature時也有屬性排序么,對,就是

?

[java]?view plain?copy
  1. objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);??

只不過@JsonPropertyOrder顆粒度要更細一點,可以決定哪些屬性優先排序

?

?

3、@JsonView

視圖模板,作用于方法和屬性上,用來指定哪些屬性可以被包含在JSON視圖中,在前面我們知道已經有@JsonIgnore和@JsonIgnoreProperties可以排除過濾掉不需要序列化的屬性,可是如果一個POJO中有上百個屬性,比如訂單類、商品詳情類這種屬性超多,而我們可能只需要概要簡單信息即序列化時只想輸出其中幾個或10幾個屬性,此時使用@JsonIgnore和@JsonIgnoreProperties就顯得非常繁瑣,而使用@JsonView便會非常方便,只許在你想要輸出的屬性(或對應的getter)上添加@JsonView即可,舉例:

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonView()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setA("1");??
  5. ????testPOJO.setB("2");??
  6. ????testPOJO.setC("3");??
  7. ????testPOJO.setD("4");??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION,?false);??
  10. ????String?jsonStr?=?objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO);??
  11. ????Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\"}",jsonStr);??
  12. ????String?jsonStr2?=?objectMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO);??
  13. ????Assert.assertEquals("{\"d\":\"4\",\"b\":\"2\"}",jsonStr2);??
  14. }??
  15. ??
  16. public?static?class?TestPOJO{??
  17. ????@JsonView(FilterView.OutputA.class)??
  18. ????private?String?a;??
  19. ????@JsonView(FilterView.OutputA.class)??
  20. ????private?String?c;??
  21. ????@JsonView(FilterView.OutputB.class)??
  22. ????private?String?d;??
  23. ????@JsonView(FilterView.OutputB.class)??
  24. ????private?String?b;??
  25. ????//getters、setters忽略??
  26. }??
  27. ??
  28. ??
  29. private?static?class?FilterView?{??
  30. ????static?class?OutputA?{}??
  31. ????static?class?OutputB?{}??
  32. }??

上面的測試用例中,我們在序列化之前先設置了objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false),看javadoc說這是一個雙向開關,開啟將輸出沒有JsonView注解的屬性,false關閉將輸出有JsonView注解的屬性,可惜我在測試中開啟開關后有JsonView注解的屬性任然輸出了,大家可以研究下。序列化時使用了objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO),即使用哪個視圖來輸出。在上面的例子中又2種視圖,我們在序列化的時候可以選擇想要的視圖來輸出,這在一些地方比較好用,比如安卓、蘋果、桌面等不同的客戶端可能會輸出不同的屬性。在1.6版本中這個@JsonView注解同時也會強制性自動發現,也就是說不管屬性的可見性以及是否設置了自動發現這些屬性都將會自動被發現,在上例中TestPOJO中的getters、setters可以不需要也能輸出我們想要的結果。

?

4、@JsonFilter

Json屬性過濾器,作用于類,作用同上面的@JsonView,都是過濾掉不想要的屬性,輸出自己想要的屬性。和@FilterView不同的是@JsonFilter可以動態的過濾屬性,比如我不想輸出以system開頭的所有屬性等待,應該說@JsonFilter更高級一點,舉個簡單的例子

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonFilter()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setA("1");??
  5. ????testPOJO.setB("2");??
  6. ????testPOJO.setC("3");??
  7. ????testPOJO.setD("4");??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????FilterProvider?filters?=?new?SimpleFilterProvider().addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));??
  10. ????objectMapper.setFilters(filters);??
  11. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  12. ????Assert.assertEquals("{\"a\":\"1\"}",jsonStr);??
  13. }??
  14. ??
  15. @JsonFilter("myFilter")??
  16. public?static?class?TestPOJO{??
  17. ????private?String?a;??
  18. ????private?String?c;??
  19. ????private?String?d;??
  20. ????private?String?b;??
  21. ??
  22. ????//getters、setters省略??
  23. }??

上面例子中在我們想要序列化的POJO上加上了@JsonFilter,表示該類將使用名為myFilter的過濾器。在測試中定義了一個名為myFilter的SimpleFilterProvider,這個過濾器將會過濾掉所有除a屬性以外的屬性。這只是最簡單的輸出指定元素的例子,你可以自己實現FilterProvider來滿足你的過濾需求。

?

有時候我們可能需要根據現有的POJO來過濾屬性,而這種情況下通常不會讓你修改已有的代碼在POJO上加注解,這種情況下我們就可以結合@JsonFilter和MixInAnnotations來實現過濾屬性,如下例所示,不再多做解釋

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonFilter()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setA("1");??
  5. ????testPOJO.setB("2");??
  6. ????testPOJO.setC("3");??
  7. ????testPOJO.setD("4");??
  8. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  9. ????FilterProvider?filters?=?new?SimpleFilterProvider().addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));??
  10. ????objectMapper.setFilters(filters);??
  11. ????objectMapper.addMixInAnnotations(TestPOJO.class,MyFilterMixIn.class);??
  12. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  13. ????Assert.assertEquals("{\"a\":\"1\"}",jsonStr);??
  14. }??
  15. ??
  16. public?static?class?TestPOJO{??
  17. ????private?String?a;??
  18. ????private?String?c;??
  19. ????private?String?d;??
  20. ????private?String?b;??
  21. ????//getters、setters省略??
  22. }??
  23. ??
  24. @JsonFilter("myFilter")??
  25. private?static?interface?MyFilterMixIn{??
  26. }??

5、@JsonIgnoreType

作用于類,表示被注解該類型的屬性將不會被序列化和反序列化,也跟上面幾個一樣屬于過濾屬性功能的注解,舉例:

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonFilter()?throws?Exception?{??
  3. ????TestPOJO?testPOJO?=?new?TestPOJO();??
  4. ????testPOJO.setName("myName");??
  5. ????Sub1?sub1?=?new?Sub1();??
  6. ????sub1.setId(1);??
  7. ????sub1.setName("sub1");??
  8. ????Sub2?sub2?=?new?Sub2();??
  9. ????sub2.setId(2);??
  10. ????sub2.setAge(22);??
  11. ????testPOJO.setMyIn(sub1);??
  12. ????testPOJO.setSub1(sub1);??
  13. ????testPOJO.setSub2(sub2);??
  14. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  15. ????String?jsonStr?=?objectMapper.writeValueAsString(testPOJO);??
  16. ????System.out.println(jsonStr);??
  17. }??
  18. ??
  19. public?static?class?TestPOJO{??
  20. ????private?Sub1?sub1;??
  21. ????private?Sub2?sub2;??
  22. ????private?MyIn?myIn;??
  23. ????private?String?name;??
  24. ????//getters、setters省略??
  25. }??
  26. ??
  27. public?static?class?MyIn{??
  28. ????private?int?id;??
  29. ????//getters、setters省略??
  30. }??
  31. ??
  32. @JsonIgnoreType??
  33. public?static?class?Sub1?extends?MyIn{??
  34. ????private?String?name;??
  35. ????//getters、setters省略??
  36. }??
  37. ??
  38. @JsonIgnoreType??
  39. public?static?class?Sub2?extends?MyIn{??
  40. ????private?int?age;??
  41. ????//getters、setters省略??
  42. }??

上面例子中我們在類Sub1和Sub2上都加上了@JsonIgnoreType,那么需要序列化和反序列時POJO中所有Sub1和Sub2類型的屬性都將會被忽略,上面測試結果為{"myIn":{"id":1,"name":"sub1"},"name":"myName"},只輸出了name和myIn屬性。需要注意的是@JsonIgnoreType是可以繼承的,即如果在基類上添加了該注解,那么子類也相當于加了該注解。在上例中,如果只在基類MyIn上添加@JsonIgnoreType那么序列化TestPOJO時將會過濾掉MyIn、Sub1、Sub2。輸出結果為{"name":"myName"}

?

?

?

?

6、@JsonAnySetter

作用于方法,在反序列化時用來處理遇到未知的屬性的時候調用,在本文前面我們知道可以通過注解@JsonIgnoreProperties(ignoreUnknown=true)來過濾未知的屬性,但是如果需要這些未知的屬性該如何是好?那么@JsonAnySetter就可以派上用場了,它通常會和map屬性配合使用用來保存未知的屬性,舉例:

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonAnySetter()?throws?Exception?{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr?=?"{\"name\":\"myName\",\"code\":\"12345\",\"age\":12}";??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("myName",testPOJO.getName());??
  7. ????Assert.assertEquals("12345",testPOJO.getOther().get("code"));??
  8. ????Assert.assertEquals(12,testPOJO.getOther().get("age"));??
  9. }??
  10. ??
  11. public?static?class?TestPOJO{??
  12. ????private?String?name;??
  13. ??
  14. ????private?Map?other?=?new?HashMap();??
  15. ??
  16. ????@JsonAnySetter??
  17. ????public?void?set(String?name,Object?value)?{??
  18. ????????other.put(name,value);??
  19. ????}??
  20. ??
  21. ????//getters、setters省略??
  22. }??

測試用例中我們在set方法上標注了@JsonAnySetter,每當遇到未知的屬性時都會調用該方法

?

7、@JsonCreator

?

?

作用于方法,通常用來標注構造方法或靜態工廠方法上,使用該方法來構建實例,默認的是使用無參的構造方法,通常是和@JsonProperty或@JacksonInject配合使用,舉例

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonCreator()?throws?Exception?{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr?=?"{\"full_name\":\"myName\",\"age\":12}";??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("myName",testPOJO.getName());??
  7. ????Assert.assertEquals(12,?testPOJO.getAge());??
  8. }??
  9. ??
  10. public?static?class?TestPOJO{??
  11. ????private?String?name;??
  12. ????private?int?age;??
  13. ??
  14. ????@JsonCreator??
  15. ????public?TestPOJO(@JsonProperty("full_name")?String?name,@JsonProperty("age")?int?age){??
  16. ????????this.name?=?name;??
  17. ????????this.age?=?age;??
  18. ????}??
  19. ????public?String?getName()?{??
  20. ????????return?name;??
  21. ????}??
  22. ????public?int?getAge()?{??
  23. ????????return?age;??
  24. ????}??
  25. }??

上面示例中是在構造方法上標注了@JsonCreator,同樣你也可以標注在靜態工廠方法上,比如:

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonCreator()?throws?Exception?{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr?=?"{\"name\":\"myName\",\"birthday\":1416299461556}";??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("myName",testPOJO.getName());??
  7. ????System.out.println(testPOJO.getBirthday());??
  8. }??
  9. ??
  10. public?static?class?TestPOJO{??
  11. ????private?String?name;??
  12. ????private?Date?birthday;??
  13. ??
  14. ????private?TestPOJO(String?name,Date?birthday){??
  15. ????????this.name?=?name;??
  16. ????????this.birthday?=?birthday;??
  17. ????}??
  18. ??
  19. ????@JsonCreator??
  20. ????public?static?TestPOJO?getInstance(@JsonProperty("name")?String?name,@JsonProperty("birthday")?long?timestamp){??
  21. ????????Date?date?=?new?Date(timestamp);??
  22. ????????return?new?TestPOJO(name,date);??
  23. ????}??
  24. ??
  25. ????public?String?getName()?{??
  26. ????????return?name;??
  27. ????}??
  28. ??
  29. ????public?Date?getBirthday()?{??
  30. ????????return?birthday;??
  31. ????}??
  32. }??

這個實例中,TestPOJO的構造方法是私有的,外面無法new出來該對象,只能通過工廠方法getInstance來構造實例,此時@JsonCreator就標注在工廠方法上。

?

除了這2種方式外,還有一種構造方式成為授權式構造器,也是我們平常比較常用到的,這個構造器只有一個參數,且不能使用@JsonProperty。舉例:

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jsonCreator()?throws?Exception?{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr?=?"{\"full_name\":\"myName\",\"age\":12}";??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("myName",testPOJO.getName());??
  7. ????Assert.assertEquals(12,testPOJO.getAge());??
  8. }??
  9. ??
  10. public?static?class?TestPOJO{??
  11. ????private?String?name;??
  12. ????private?int?age;??
  13. ????@JsonCreator??
  14. ????public?TestPOJO(Map?map){??
  15. ????????this.name?=?(String)map.get("full_name");??
  16. ????????this.age?=?(Integer)map.get("age");??
  17. ????}??
  18. ??
  19. ????public?String?getName()?{??
  20. ????????return?name;??
  21. ????}??
  22. ??
  23. ????public?int?getAge()?{??
  24. ????????return?age;??
  25. ????}??
  26. }??

8、@JacksonInject

作用于屬性、方法、構造參數上,被用來反序列化時標記已經被注入的屬性,舉例:

?

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jacksonInject()?throws?Exception?{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr?=?"{\"age\":12}";??
  5. ????InjectableValues?inject?=?new?InjectableValues.Std().addValue("name","myName");??
  6. ????TestPOJO?testPOJO?=?objectMapper.reader(TestPOJO.class).with(inject).readValue(jsonStr);??
  7. ????Assert.assertEquals("myName",?testPOJO.getName());??
  8. ????Assert.assertEquals(12,testPOJO.getAge());??
  9. }??
  10. ??
  11. public?static?class?TestPOJO{??
  12. ????@JacksonInject("name")??
  13. ????private?String?name;??
  14. ????private?int?age;??
  15. ??
  16. ????//getters、setters省略??
  17. }??

上面例子中我們在反序列化前通過InjectableValues來進行注入我們想要的屬性

?

9、@JsonPOJOBuilder

?

?

作用于類,用來標注如何定制構建對象,使用的是builder模式來構建,比如Value v = new ValueBuilder().withX(3).withY(4).build();這種就是builder模式來構建對象,通常會喝@JsonDeserialize.builder來配合使用,我們舉個例子:

?

[java]?view plain?copy
  1. @Test??
  2. public?void?jacksonInject()?throws?Exception?{??
  3. ????ObjectMapper?objectMapper?=?new?ObjectMapper();??
  4. ????String?jsonStr?=?"{\"name\":\"myName\",\"age\":12}";??
  5. ????TestPOJO?testPOJO?=?objectMapper.readValue(jsonStr,TestPOJO.class);??
  6. ????Assert.assertEquals("myName",?testPOJO.getName());??
  7. ????Assert.assertEquals(12,testPOJO.getAge());??
  8. }??
  9. ??
  10. @JsonDeserialize(builder=TestPOJOBuilder.class)??
  11. public?static?class?TestPOJO{??
  12. ????private?String?name;??
  13. ????private?int?age;??
  14. ??
  15. ????public?TestPOJO(String?name,?int?age)?{??
  16. ????????this.name?=?name;??
  17. ????????this.age?=?age;??
  18. ????}??
  19. ??
  20. ????public?String?getName()?{??
  21. ????????return?name;??
  22. ????}??
  23. ??
  24. ????public?int?getAge()?{??
  25. ????????return?age;??
  26. ????}??
  27. }??
  28. ??
  29. @JsonPOJOBuilder(buildMethodName?=?"create",withPrefix?=?"with")??
  30. public?static?class?TestPOJOBuilder{??
  31. ????private?String?name;??
  32. ????private?int?age;??
  33. ??
  34. ????public?TestPOJOBuilder?withName(String?name)?{??
  35. ????????this.name?=?name;??
  36. ????????return?this;??
  37. ????}??
  38. ??
  39. ????public?TestPOJOBuilder?withAge(int?age)?{??
  40. ????????this.age?=?age;??
  41. ????????return?this;??
  42. ????}??
  43. ??
  44. ????public?TestPOJO?create()?{??
  45. ????????return?new?TestPOJO(name,age);??
  46. ????}??
  47. }??

在TestPOJOBuilder上有@JsonPOJOBuilder注解,表示所有的參數傳遞方法都是以with開頭,最終構建好的對象是通過create方法來獲得,而在TestPOJO上使用了@JsonDeserializer,告訴我們在反序列化的時候我們使用的是TestPOJOBuilder來構建此對象的

?


還有一些過期不推薦使用的注解,我們一筆帶過,主要知道他們是跟哪些其他注解功能一樣即可

?

@JsonGetter

作用于方法,1.0版本開始的注解,已經過期,不推薦使用,改用@JsonProperty
@JsonUseSerializer

作用于類和方法,1.5版本開始被移除了,改用@JsonSerialize

@JsonSetter
作用于方法,1.0版本開始的注解,已過期,不推薦使用,改用@JsonProperty

@JsonClass

作用于方法和類,1.9版本開始被移除了,改為@JsonDeserialize.as

@JsonContentClass

作用于方法,1.9版本開始被移除了,改為@JsonDeserialize.contentAs

@JsonKeyClass

作用于方法和類,1.9版本開始被移除了,改為@JsonDeserialize.keyAs

@JsonUseDeserializer

作用于方法和類,1.5版本開始被移除了,改為@JsonDeserialize
?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/450678.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450678.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450678.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JS-for的衍生對象

在js中一般使用方法&#xff1a; 1.常規的for(var i0;i<length;i) 2.for-in:for(var item in list) 3.for of 描述&#xff1a;對應于一個對象的每個屬性&#xff0c;或一個數組的每個元素&#xff0c;執行一個或多個語句。 語法&#xff1a;for (variable in [object | ar…

浮點數在計算機中存儲方式

C語言和C#語言中&#xff0c;對于浮點類型的數據采用單精度類型&#xff08;float&#xff09;和雙精度類型(double)來存儲&#xff0c;float數據占用32bit,double數據占用64bit,我們在聲明一個變量float f 2.25f的時候&#xff0c;是如何分配內存的呢&#xff1f;如果胡亂分配…

操作系統面試題目詳解

文章目錄1.13 什么是協程&#xff1f;1.14 為什么協程比線程切換的開銷小&#xff1f;1.15 線程和進程的區別&#xff1f;1.16 進程切換為什么比線程更消耗資源&#xff1f;1.17 介紹一下進程之間的通信。1.18 介紹一下信號量。1.19 說說僵尸進程和孤兒進程。1.20 請介紹進程之…

(項目)在線教育平臺(六)

八、授課機構功能 1、模板繼承 如果幾個頁面的大體結構相同&#xff0c;可以使用繼承的方式來實現母版的重用性&#xff0c;也就是子版繼承母版的內容&#xff0c;既可以使用模板的內容&#xff0c;也可以重寫需要改變的地地方。 首先完成授課機構的頁面&#xff0c;通過頁面顯…

C語言 socket 編程學習

對于SOCKET在這里我不想究其歷史,我只想說其時它是一種進程通訊的方式,簡言之就是調用這個網絡庫的一些API函數就能實現分布在不同主機的相關進程之間的數據交換. SOCKET中首先我們要理解如下幾個定義概念: 一是IP地址:IP Address我想很容易理解,就是依照TCP/IP協議分配…

dependency 中的 classifier屬性

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 classifier元素用來幫助定義構件輸出的一些附屬構件。附屬構件與主構件對應&#xff0c;比如主構件是 kimi-app-2.0.0.jar 該項目可能還…

PHP超全局變量$_SERVER

$_SERVER 是一個包含了諸如頭信息(header)、路徑(path)、以及腳本位置(script locations)等等信息的數組。這個數組中的項目由 Web 服務器創建。不能保證每個服務器都提供全部項目&#xff1b;服務器可能會忽略一些&#xff0c;或者提供一些沒有在這里列舉出來的項目。 $_SERVE…

VC讀寫XML文件

1、安裝MSXML 4.0 SP2。在VC6中建立一個基于Dialog的工程。如圖&#xff1a; 在界面上放置3個編輯框、1個按鈕控件。其中屬性設置如下。 編輯框&#xff1a; IDCategoryVariable TypeVariable NameIDC_IDValueCStringm_strIdIDC_AUTHORValueCStringm_strAuthorIDC_TITLEValueCS…

XCode10 swift4.2 適配遇到的坑

以下是2018年10月23日更新 經過大約一個月的時間的適配&#xff0c;項目正式使用XCode10(以下簡稱為10 or XC10)大部分庫都升級為Swift4.2&#xff08;以下簡稱為 4.2 or S4.2&#xff09;&#xff0c;下面是適配過程中遇到的一些坑。 1. Swift4、Swift4.2混編 如果你對項目是小…

學生管理系統Java版

簡單的學生管理系統 主界面編寫&#xff1a; 1.用輸出語句完成主界面的編寫 2.用Scanner語句實現鍵盤的錄入 3.用swich語句完成操作的選擇 4.用循環完成再次回到主界面 代碼實現&#xff1a; while (true) {//1.用輸出語句完成主界面的編寫System.out.println("--------…

dubbo 配置文件詳解

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一、dubbo常用配置 <dubbo:service/> 服務配置&#xff0c;用于暴露一個服務&#xff0c;定義服務的元信息&#xff0c;一個服務可…

ASP.NET Core 實戰:Linux 小白的 .NET Core 部署之路

一、前言 最近一段時間自己主要的學習計劃還是按照畢業后設定的計劃&#xff0c;自己一步步的搭建一個前后端分離的 ASP.NET Core 項目&#xff0c;目前也還在繼續學習 Vue 中&#xff0c;雖然中間斷了很長時間&#xff0c;好歹還是堅持下來了&#xff0c;嗯&#xff0c;看了看…

學以致用十三-----Centos7.2+python3+YouCompleteMe成功歷程

歷經幾天的摸索&#xff0c;趟過幾趟坑之后&#xff0c;終于完成YouCompleteMe的安裝配置。 今天同樣是個不能忘記的日子&#xff0c;國恥日&#xff0c;勿忘國恥。&#xff08;9.18&#xff09; 服務器安裝好&#xff0c;基本配置配置好后&#xff0c;開始安裝。 一、檢查服務…

VC畫圖用到的主要方法

1。鼠標落下&#xff0c;記錄鼠標的起始位置 void CMyEasyDrawView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 //graph->m_nTypedlg-> m_bStartDraw true; m_PtPress m_PtLast point; CView::OnLButtonDown…

【最新版】Java學習路線(含B站口碑推薦視頻鏈接)

文章目錄關于如何自學一、計算機網絡二、數據結構與算法三、操作系統四、計算機組成原理五、編譯原理六、設計模式七、MySQL八、實操工具九、JAVA并發與JVM十、Redis十一、Linux十二、Java路線學習尚硅谷黑馬程序員動力節點狂神說十三、Java基礎十四、JavaWeb十五、框架十六、微…

記錄no static method cannot be reference

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; no static method cannot be reference 我一直以為是在靜態方法中調用了非靜態方法&#xff0c;實際上只是我在注…

文件存儲權限

Android 6.0及以上&#xff0c;需要動態申請權限&#xff1a; Manifest.permission.READ_EXTERNAL_STORAGE Manifest.permission.WRITE_EXTERNAL_STORAGE <uses-permission-sdk-23 android:name"android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permis…

從工具的奴隸到工具的主人

摘要&#xff1a;我們每個人都是工具的奴隸。隨著我們的學習&#xff0c;我們不斷的加深自己對工具的認識&#xff0c;從而從它們里面解脫出來。現在我就來說一下我作為各種工具的奴隸&#xff0c;以及逐漸擺脫它們的思想控制的歷史吧。 當我高中畢業進入大學計算機系的時候&am…

記錄A component required a bean named ‘studentService‘ that could not be found.

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; A component required a bean named studentService that could not be found. 出問題的代碼行&#xff1a; &l…

Java---利用程序實現在控制臺聊天

一.普通版&#xff08;不能實現隨意輸入&#xff09; 電腦A(服務器端) package day; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner;public class Mysever {public static void…