反序列化 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