反序列化 jackson
Datatables是一個jquery插件,用于顯示表格資訊–它可以增強簡單的表或可以使用基于AJAX的資料并以表格形式顯示資訊。
資料表要求來自伺服器的資料遵循特定的JSON格式才能在螢幕上顯示。 考慮要顯示Member實體清單的情況,那麼Member的預期json結構必須遵循以下幾行:
{
'aaData':[
{
'id':1,
'first':'one',
'last':'one',
'addresses':[
],
'version':0
},
{
'id':2,
'first':'two',
'last':'two',
'addresses':[
],
'version':0
}
],
'iTotalRecords':100,
'iTotalDisplayRecords':10,
'success':true
}
可以定義一個通用的Java類型, Jackson可以使用它來生成上述類型的json,請考慮以下Java通用類型:
package mvcsample.types;
import java.util.List;
public class ListWrapper<T> {
private List<T> aaData;
private int iTotalRecords;
private int iTotalDisplayRecords;
private Boolean success;
public List<T> getAaData() {
return aaData;
}
public void setAaData(List<T> aaData) {
this.aaData = aaData;
}
public int getiTotalRecords() {
return iTotalRecords;
}
public void setiTotalRecords(int iTotalRecords) {
this.iTotalRecords = iTotalRecords;
}
public int getiTotalDisplayRecords() {
return iTotalDisplayRecords;
}
public void setiTotalDisplayRecords(int iTotalDisplayRecords) {
this.iTotalDisplayRecords = iTotalDisplayRecords;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
}
是以,使用此泛型類型,要生成成員清單,我将具有如本測試中定義的參數化類型:
List<Member> members = new ArrayList<>();
members.add(new Member('one', 'one'));
members.add(new Member('two', 'two'));
ListWrapper<Member> membersWrapper = new ListWrapper<>();
membersWrapper.setAaData(members);
membersWrapper.setiTotalDisplayRecords(10);
membersWrapper.setiTotalRecords(100);
ObjectMapper objectMapper = new ObjectMapper();
StringWriter w = new StringWriter();
objectMapper.writeValue(w, membersWrapper);
String json = w.toString();
System.out.println(json);
同樣,可以生成任何其他類型的json。
但是, 相反,生成給定json的Java類型呢?
再次考慮一下将開頭給出的json轉換為ListWrapper <Member>的情況,我可以這樣嘗試反序列化:
ObjectMapper objectMapper = new ObjectMapper();
ListWrapper<Member> membersUpdated = objectMapper.readValue(json, ListWrapper.class);
請注意,以上我無法将類類型稱為ListWrapper <Member> .class,而隻能将其稱為ListWrapper.class。
但是,這将不起作用,并且結果類型也不會成為Member類的包裝器,因為在運作時Jackson并不知道必須生成ListWrapper <Member>。
解決方法是以某種方式将有關ListWrapper類型的資訊傳遞給Jackson,這就是Super類型标記所适合的地方。 本文詳細說明了它的工作原理,其實質是,盡管類型擦除确實從參數化執行個體的類型執行個體中删除了類型資訊。泛型類型,但是類型保留在泛型類的子類中。
例如。 考慮以下從ArrayList <String>派生的StringList類,可以發現基類的類型參數是String,如下面的測試所示:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
public class StringList extends ArrayList<String>{
public static void main(String[] args) {
StringList list = new StringList();
Type superClassType = list.getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType)superClassType;
System.out.println(parameterizedType.getActualTypeArguments()[0]);
}
}
這同樣适用于子類也被定義為匿名類的情況:
ArrayList<String> list = new ArrayList<String>(){};
Type superClassType = list.getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType)superClassType;
System.out.println(parameterizedType.getActualTypeArguments()[0]);
這是Super Type令牌模式在内部使用的功能,用于查找參數化類型的類型。 Jackson的com.fasterxml.jackson.core.type.TypeReference抽象類實作了此功能,使用此功能,Jackson反序列化将以這種方式工作:
import com.fasterxml.jackson.core.type.TypeReference;
....
ListWrapper<Member> membersWrapper = objectMapper.readValue(json, new TypeReference<ListWrapper<Member>>() {});
ListWrapper<Address> addressWrapper = objectMapper.readValue(json, new TypeReference<ListWrapper<Address>>() {});
這樣,可以在給定通用類型和json表示的情況下反序列化兩個不同的參數化類型。
資源:
- 反映泛型 :http://www.artima.com/weblogs/viewpost.jsp? thread = 208860
- 尼爾·古夫特(Neal Gafter)的超級類型令牌 :http://gafter.blogspot.com/2006/12/super-type-tokens.html
參考: all和雜物部落格上的Json 合作夥伴 Biju Kunjummen的Jackson和Super類型代币對Json的反序列化 。
翻譯自: https://www.javacodegeeks.com/2013/01/json-deserialization-with-jackson-and-super-type-tokens.html
反序列化 jackson