使用Jackson和Super类型令牌进行Json反序列化

Datatables是一个jquery插件,用于显示表格信息–它可以增强简单的表或可以使用基于AJAX的数据并以表格形式显示信息。

数据表要​​求来自服务器的数据遵循特定的JSON格式才能在屏幕上显示。 考虑要显示成员实体列表的情况,那么对于成员而言,预期的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类,可以发现基类的type参数是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表示的情况下反序列化两个不同的参数化类型。

资源:

参考: all和杂物博客中的Json用我们的JCG合作伙伴 Biju Kunjummen的Jackson和Super类型令牌进行反序列化

翻译自: https://www.javacodegeeks.com/2013/01/json-deserialization-with-jackson-and-super-type-tokens.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值