您的位置:首页 > 编程语言 > Java开发

java手动拼接Ext组件json数据的简单方法

2011-01-06 16:28 417 查看
Ext的很多组件如grid, comboBox, tree等都有自己json数据格式, 一般我们需要在后台把数据库的数据进行拼接返回给前端。 以前我一直使用的是json-lib这个库,进行java object的json格式化的; 也有过一段时间是自己手动拼接json的。 这个2个办法在用过多次之后都有些不方便的地方:

使用json-lib:

这个库可以把对象,数组相应的转换成json格式。例如grid来说,我一般直接把实体对象转换成数组,以后还要拼接一下grid需要的一些数据。或者自己手动写个类型就是是grid对象的json格式,生成对象后直接转换也可以。

可是有时候,没必要传送那么多数据回去,一行表的字段也许仅仅需要几个而已。

遇到外键字段,json-lib就是不知道怎么转化了。所以这样就要自定义一个类去封装。

手动拼接:

有时候我还喜欢这么搞,简单明了的。但对于数据比较多,或是大量使用情况。就会纠缠在无数的StringBuilder的append中间。大量的"'"符号,不同字段的get方法,“,”的处理让人很抓狂,也很重复很无聊。

下面我总结了一个比较简单的手动拼接的方法,以ext grid为例子。

{
results: 2000, // Reader's configured totalProperty
rows: [        // Reader's configured root
// record data objects:
{ id: 1, firstname: 'Bill', occupation: 'Gardener' },
{ id: 2, firstname: 'Ben' , occupation: 'Horticulturalist' },
...
]
}


这是一个grid的接受数据的标准格式, 可以看到有些东西是固有的,比如都是{}, result, rows, [], {}这样的。后台拼接的时候,真正动态的就是rows里面的每一行,列名和列数据,如 id 和 1这样的。其它的都是固定的格式。我的这个方法的核心就是,变与不变的分离。不变的是固定的格式,什么时候[], 什么时候{} 等等; 变化就是存放在实体对象中的属性名和属性值。

一步步来,首先,我们需要一个接口,它的职责就是实现一个方法可以返回变化的数据。变化的数据我们可以看出来,是k-v的形式,属性值和属性名。属性名永远是string类型,值则是任意的。看接口定义如下:

/**
* 提供获得对象属性名值数据的接口
*
* @author scottCgi
* @since  2010-12-26
* @param <T>
*/
public static interface IProperty<T> {
/**
* 获得对象属性值和名的数组
*
* @param  object 需要提取数据的对象
* @return 对象属性值和名的数组
*/
Object[] getProperty(T object);
}


这个接口我是定义在action基础类里的,所以是static的当然可以不这么做。这个接口只有一个方法,他有一个参数就是需要提取变化数据的对象,就是实体对象,这里是泛型的因为实体对象类型运行时确定。 返回值是一个Object数组,我没有用map类型数据格式来存放k-v。而是约定,这个数组每2项为一个整体存放k和v。为什么是Object因为刚才说了,实体对像的属性值是任何的可能类型,所以统一看成老祖宗类型。

接下来,需要一个方法来提取实体对象中的可变数据,如下:

/**
* 拼接对象json字符辅助对象
*
* @param sb          存放json的StringBuilder对象
* @param entityList  实体对象列表
* @param property    需要返回的实体对象属性名和值
*/
private void getObjectJson(StringBuilder sb, List<T> entityList, IProperty<T> property) {
Object[] objects = null;
for(T entity : entityList) {
objects = property.getProperty(entity);
sb.append("{");
for(int i = 0; i < objects.length; i += 2) {
sb.append("'").append(objects[i]).append("':'").append(objects[i + 1]).append("',");
}

sb.replace(sb.lastIndexOf(","), sb.length(), "").append("},");
}

if(entityList.size() != 0) {
sb.replace(sb.lastIndexOf(","), sb.length(), "");
}
}


因为Grid中的可变数据就是rows里的东西,所以可变json数据只是grid json整体的一部分,这个方法里的sb就是整体的json, 传入到这个方法表明需要完成整理中,rows里可变数据的部分。 entityList就是rows里的数据行, 每一行的数据如何拼接呢? 这就以来刚才定义的那个接口。property所引用的是一个实现了接口方法的对象。 方法调用中,我们看到我给接口方法传进去了Object, 而方法为我们返回 k-v形式的可变数据,我们进行json格式的拼装。

再往后呢,我们来看看grid 整体json是如何构建的:

/**
* 获得实体对象列表的grid json字符串
*
* @param <T>
* @param entityList  实体对象列表
* @param totalCount  实体对象总数据数
* @param property    需要返回的实体对象属性名和值
* @return            实体对象列表的grid json字符串
*/
public String getGridJson(List<T> entityList, long totalCount, IProperty<T> property) {
StringBuilder sb = new StringBuilder();
sb.append("{")
.append("totalCount:")
.append(totalCount)
.append(",")
.append("rows: [");

this.getObjectJson(sb, entityList, property);
sb.append("]}");
return sb.toString();
}


这个方法构建了grid的整体json, 方法中体用了getObjectJson去构建可变数据部分。 property依然是作为参数传递进来的。 由此可见这个接口是让使用者自己实现的。 因为一个对象那些属性需要拼接成json是需要具体对待的。

最后我们看看如何使用这些:

@Override
public String getGridJson(Page<Cinema> page) {
return this.getGridJson(page.getResult(), page.getTotalCount(), new IProperty<Cinema>(){
@Override
public Object[] getProperty(Cinema o) {
return new Object[]{
"id", o.getId(),
"name", o.getName(),
"introduce", o.getIntroduce(),
"information", o.getInformation()
};
}
});
}


这是一个重载了getGridJson的方法,参数是一个page对象, 分页对象是从数据库查询出来的。 page对象可以获得数据的总行数,和实体对象列表,这正是原getGridJson说需要的。 那么剩下一个IProperty接口,我们就地new了一个匿名类,实现了唯一的一个方法。由于是泛型的类型,我们在实现方法中拿到了具体的类型,这样我们就地new了一个Objcet数组直接初始化了。 数据就如同前面约定的,一个值是属性名,一个值是属性值。

在action中得到page对象后,直接调用这个方法就可以得到grid json了。实体对象需要的属性,由具体重载的getGridJson去定制,这样如果是外键对象也可以根据需要get出具体的属性k-v。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: