DirectJNgine——关于泛型的Json序列化

问题描述:在采用DirectJNgine来完成前端ExtJS4和Java后台数据交互过程中,出现以下问题:前端通过ExtJS框架的DirectStore从后台请求数据,由于Store请求数据的格式基本不变,大概由以下字段构成:请求是成功的标志,记录总条数,返回到前端的数据(通常是一个集合)。对于这个集合,首先想到是泛型,泛化的类型为返回到前端的Model。所以,DirectMethod通常是以下形式:

 

/**
  * 用户列表.   */
 @DirectMethod
 public DataStore<User> list(int start, int limit, String sort, String dir) {
  List<User> users = new Vector<Users>();  //添加一些user
  return new DataStore<User>(this.users.size(), users, true);
 }

 

DataStore为:

 

public class DataStore<T> {
	/**
	 * 包含数据集合的属性名, 默认为空.
	 * <p>
	 * 约定前端data.Reader的包含数据集合的属性名(root属性)为data.
	 * </p>
	 */
	private List<T> data;

	/**
	 * 记录总条数.
	 * <p>
	 * 前端data.Reader的记录总条数totalProperty的属性名称默认为total.
	 * </p>
	 */
	private int total;

	/**
	 * 指示请求是否成功.
	 * <p>
	 * 默认为成功.
	 * </p>
	 */
	private boolean success = true;               
	// 构造方法,以及getters和setters...
}

 

 我觉得这是一个看上去比较完美的的模型。但是在使用的过程中,后端会抛以下异常:

 

 

java.lang.UnsupportedOperationException: Expecting parameterized type
Are you missing the use of TypeToken idiom?
See http://sites.google.com/site/gson/gs...ializing-Gener
at com.google.gson.TypeInfoFactory.getActualType(TypeInfoFactory.java:97)

 

原因是Gson不能正确解析DataStore<User>。经过做一些实验,验证如果返回的是泛型,而且类内部有使用泛型实例,则Gson解析通不过。实验请参看帖子Ext Direct Java based implementation #395 .

 

分析:通过Gson是可以解析泛型的,方法是把泛型的实际类型传给fromJson方法,如:

 

 

DataStore<User> usersStore = new DataStore<User>();
// 添加 users 到usersStore
Type listType = new TypeToken<DataStore<User>() {}.getType();
gson.toJson(myStrings, listType); 

 

但是DJN当前还没有完美得解决这个问题,作者的建议是尽量不要采用泛型作为返回值。DJN作者的解释的见Ext Direct Java based implementation #396 。由于DJN处理Json的宗旨”尽量避免Json序列化的工作”的限制,很多功能还不能完美的解决,比如说循环引用,属性排除等,这在一定程度上消弱了Gson本身的功能。关于这方面的问题,我还会继续和作者沟通,看看在将来的版本能否有一个好的解决方案。最新动态请关注上面的帖子和DJN的官网

 

解决方案:我最终将DataStore类设计为以下形式:

 

 

/**
 * 返回到前端的数据仓库.
 * <p>
 * 用户返回给前端Store的请求.
 * <p>
 * 
 * @author feiq
 * 
 */
public class DataStore {
	public DataStore() {

	}

	@SuppressWarnings("rawtypes")
	public DataStore(int total, List data) {
		this.total = total;
		this.data = data;
	}

	@SuppressWarnings("rawtypes")
	/**
	 * 包含数据集合的属性名, 默认为空.
	 * <p>
	 * 约定前端data.Reader的包含数据集合的属性名(root属性)为data.
	 * </p>
	 */
	private List data;

	@SuppressWarnings("rawtypes")
	public DataStore(int total, List data, boolean success) {
		this.total = total;
		this.success = success;
		this.data = data;
	}

	/**
	 * 记录总条数.
	 * <p>
	 * 前端data.Reader的记录总条数totalProperty的属性名称默认为total.
	 * </p>
	 */
	private int total;

	/**
	 * 指示请求是否成功.
	 * <p>
	 * 默认为成功.
	 * </p>
	 */
	private boolean success = true;

	// getters and setters...
}

 

这样既可以避免泛型序列化的问题,也可以避免继承泛型类的大量子类,如

 

class UsersStore extends DataStore<User>{
     // ...
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值