NO IMAGE

一、Jackson簡介

Jackson是一個簡單基於Java應用庫,Jackson可以輕鬆的將Java物件轉換成json物件和xml文件,同樣也可以將json、xml轉換成Java物件。Jackson所依賴的jar包較少,簡單易用並且效能也要相對高些,並且Jackson社群相對比較活躍,更新速度也比較快。

特點:

  • 容易使用 – jackson API提供了一個高層次外觀,以簡化常用的用例。
  • 無需建立對映 – API提供了預設的對映大部分物件序列化。
  • 效能高 – 快速,低記憶體佔用,適合大型物件圖表或系統。
  • 乾淨的JSON – jackson建立一個乾淨和緊湊的JSON結果,這是讓人很容易閱讀。
  • 不依賴 – 庫不需要任何其他的庫,除了JDK。
  • 開原始碼 – jackson是開源的,可以免費使用。

三種方式處理JSON:

(1)流式API

讀取並將JSON內容寫入作為離散事件。 JsonParser讀取資料,而JsonGenerator寫入資料。它是三者中最有效的方法,是最低的開銷和最快的讀/寫操作。它類似於Stax解析器XML。

(2)樹模型

準備JSON檔案在記憶體裡以樹形式表示。 ObjectMapper構建JsonNode節點樹。這是最靈活的方法。它類似於XML的DOM解析器。

(3)資料繫結

轉換JSON並從POJO(普通Java物件)使用屬性訪問或使用註釋。它有兩個型別:

  • 簡單的資料繫結:轉換JSON和Java Maps, Lists, Strings, Numbers, Booleans 和null 物件。
  • 全部資料繫結:轉換為JSON從任何JAVA型別。

ObjectMapper讀/寫JSON兩種型別的資料繫結。資料繫結是最方便的方式是類似XML的JAXB解析器。

jar包:

jackson-all-1.9.0.jar

二、Jackson簡單示例

2.1 Product實體類

package com.struts2.fileupload.domain;
import java.util.Date;
import org.apache.struts2.json.annotations.JSON;
//@JsonIgnoreProperties({ "id", "releaseDate" }) //用註解方式過濾掉多個屬性
//@JsonFilter("productFilter")
public class Product {
// @JsonIgnore //用註解方式過濾掉的屬性
private int id;
private String name;
private double price;
// @JsonIgnore //用註解方式過濾掉的屬性
private Date releaseDate;// 出生日期
// @JSON(serialize = false) //用註解方式過濾掉的屬性,這樣導致全域性忽略releaseDate屬性
public Date getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}
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 double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}

2.2 JacksonTest測試類

package com.struts2.fileupload.json;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ser.FilterProvider;
import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;
import org.junit.Test;
import com.struts2.fileupload.domain.Product;
public class JacksonTest {
// 將Product轉換成json
@Test
public void test1() throws JsonGenerationException, JsonMappingException, IOException {
Product p = new Product();
p.setId(1);
p.setName("電視機");
p.setPrice(2000);
p.setReleaseDate(new Date());
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd")); // 設定日期格式化器
String json = mapper.writeValueAsString(p);
System.out.println(json);
}
// 將List<Product>轉換成json
@Test
public void test2() throws JsonGenerationException, JsonMappingException, IOException {
Product p1 = new Product();
p1.setId(1);
p1.setName("電視機");
p1.setPrice(2000);
Product p2 = new Product();
p2.setId(2);
p2.setName("電冰箱");
p2.setPrice(3000);
List<Product> ps = new ArrayList<Product>();
ps.add(p1);
ps.add(p2);
ObjectMapper mapper = new ObjectMapper();
// 不同的方法過濾不同的屬性,編碼方式實現,處理過濾屬性,注意:需要在實體類上新增@JsonFilter("productFilter"),productFilter名稱必須保持一致
//		FilterProvider fp = new SimpleFilterProvider().addFilter("productFilter",
//				SimpleBeanPropertyFilter.filterOutAllExcept("id", "name")); //只包含id與name
FilterProvider fp = new SimpleFilterProvider().addFilter("productFilter",
SimpleBeanPropertyFilter.serializeAllExcept("id", "name")); //不包含id與name
mapper.setFilters(fp);
String json = mapper.writeValueAsString(ps);
System.out.println(json);
}
}

三、Jackson的常用註解

3.1 @JsonAutoDetect

開啟/禁止自動檢測,作用在類上

屬性:

fieldVisibility:欄位的可見級別

  • ANY:任何級別的欄位都可以自動識別
  • NONE:所有欄位都不可以自動識別
  • NON_PRIVATE:非private修飾的欄位可以自動識別
  • PROTECTED_AND_PUBLIC:被protected和public修飾的欄位可以被自動識別
  • PUBLIC_ONLY:只有被public修飾的欄位才可以被自動識別
  • DEFAULT:同PUBLIC_ONLY

Jackson預設的欄位屬性發現規則如下:

所有被public修飾的欄位->所有被public修飾的getter->所有被public修飾的setter

3.2 @JsonIgnore

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

示例:

// @JsonIgnore //用註解方式過濾掉的屬性
private int id;
private String name;
private double price;
// @JsonIgnore //用註解方式過濾掉的屬性
private Date releaseDate;// 出生日期

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

3.3 @JsonProperty

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

@JsonProperty("product_name")
private String name;
private double price;

3.4 @JsonIgnoreProperties

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

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

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

示例:

@JsonIgnoreProperties({ "id", "releaseDate" }) //用註解方式過濾掉多個屬性
public class Product {
private int id;
private String name;
private Date releaseDate;// 出生日期
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 Date getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}
}

3.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省略  
}  

在2.0 版本中@JsonUnwrapped新增了prefix和suffix屬性,用來對欄位新增前字尾,這在有關屬性分組上比較有用,在上面的測試用例中,如果我們將TestPOJO的name屬性上的@JsonUnwrapped新增前字尾配置,即

@JsonUnwrapped(prefix = "name_",suffix = "_test")  

那麼TestPOJO序列化後將為{“id”:111,”name_firstName_test”:”張”,”name_secondName_test”:”三”},反序列化時也要加上前字尾才會被解析為POJO

3.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省略  
}  

3.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;  
}  
}  

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

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;  
}  
}  

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

示例:

@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;  
}  
}  

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

示例:

@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;  
}  
}  

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

ObjectMapper objectMapper = new ObjectMapper();  
objectMapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy()); 

3.8 @JsonTypeInfo

作用於類/介面,被用來開啟多型型別處理,對基類/介面和子類/實現類都有效

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property = "name")  

這個註解有一些屬性,

use:定義使用哪一種型別識別碼,它有下面幾個可選值:

  • JsonTypeInfo.Id.CLASS:使用完全限定類名做識別
  • JsonTypeInfo.Id.MINIMAL_CLASS:若基類和子類在同一包類,使用類名(忽略包名)作為識別碼
  • JsonTypeInfo.Id.NAME:一個合乎邏輯的指定名稱
  • JsonTypeInfo.Id.CUSTOM:自定義識別碼,由@JsonTypeIdResolver對應,稍後解釋
  • JsonTypeInfo.Id.NONE:不使用識別碼

include(可選):指定識別碼是如何被包含進去的,它有下面幾個可選值:

  • JsonTypeInfo.As.PROPERTY:作為資料的兄弟屬性
  • JsonTypeInfo.As.EXISTING_PROPERTY:作為POJO中已經存在的屬性
  • JsonTypeInfo.As.EXTERNAL_PROPERTY:作為擴充套件屬性
  • JsonTypeInfo.As.WRAPPER_OBJECT:作為一個包裝的物件
  • 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。

3.9 @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")})

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

3.10 @JsonTypeName

作用於子類,用來為多型子類指定型別識別符號的值

比如:

@JsonTypeName(value = "sub1")  

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

3.11 @JsonTypeName

作用於子類,用來為多型子類指定型別識別符號的值

@JsonTypeName(value = "sub1")  

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

[email protected]和@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省略  
}  

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

下面我們在基類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());  
}  
}  

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

可能我們在反序列化時覺得如此傳遞識別碼很不友好,最好可以自定義識別碼的值,可以選擇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"));

[email protected]和@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;  
}  
}  

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

也可以通過使用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    
'}';  
}  
}  

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

最後@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省略  
}  

[email protected]

作用在類上,被用來指明當序列化時需要對屬性做排序,它有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省略  
}  

我們先看一個預設的排序方式,序列化單元測試結果依次為{“a”:”1″,”c”:”3″,”d”:”4″,”b”:”2″},即是沒有經過排序操作的,在TestPOJO上加上@jsonPropertyOrder(alphabetic = true)再執行測試結果將會為{“a”:”1″,”b”:”2″,”c”:”3″,”d”:”4″}
還有一個屬性是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省略  
}  

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

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

objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true); 

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

[email protected]

檢視模板,作用於方法和屬性上,用來指定哪些屬性可以被包含在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 {}  
}  

上面的測試用例中,我們在序列化之前先設定了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可以不需要也能輸出我們想要的結果。

[email protected]

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上加上了@JsonFilter,表示該類將使用名為myFilter的過濾器。在測試中定義了一個名為myFilter的SimpleFilterProvider,這個過濾器將會過濾掉所有除a屬性以外的屬性。這只是最簡單的輸出指定元素的例子,你可以自己實現FilterProvider來滿足你的過濾需求。

有時候我們可能需要根據現有的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{  
}  

[email protected]

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

@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省略  
}  

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

[email protected]

作用於方法,在反序列化時用來處理遇到未知的屬性的時候呼叫,在本文前面我們知道可以通過註解@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省略  
}  

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

[email protected]

作用於方法,通常用來標註構造方法或靜態工廠方法上,使用該方法來構建例項,預設的是使用無參的構造方法,通常是和@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;  
}  
}  

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

@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;  
}  
}  

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

除了這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;  
}  
}  

[email protected]

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

@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省略  
}  

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

3.20 @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);  
}  
}  

在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