转载请标明出处: http://fuliang.iteye.com/blogs/1141293
内容系统需要做分类、抽取等的评测工具,这个工具每次评测的对象需要的字段不一样,可以是一项或多项内容结合的评估。我们希望能够动态定义这些评测的字段,并且这些字段供给ExtJS的表格展现。
ExtJS所consume的JS格式非常固定,所以需要转化成这种固定的格式才能正确展现。所以我们对评估对象targets定义了几个固定的字段id,url,version和动态定义的评测字段evaljson的json字符串。
[quote]
id | url | evaljson | version
----+-----------------------+-------------------------------------------------------------------------+---------
1 | http://www.tuniu.com/ | {"md5":"856f509af96b3c68dccca042d6a21729","xianlu_confidence":0.732410} | 0
2 | http://www.tuniu.com/ | {"md5":"856f509af96b3c68dccca042d6a21729","xianlu_confidence":0.932410} | 1
[/quote]
这样我们写了模型:
package com.qunar.search.evaltool.model;
public class EvalTarget {
private Long id;
private String url;
private Long version;
private String evalJson;
//getter setter equals hashcode ....
}
这个直接和数据库的字段对应,方便使用mybatis从数据库取出,分页省略:
package com.qunar.search.evaltool.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import com.qunar.search.evaltool.model.EvalTarget;
@Repository
public interface EvalTargetDAO {
@Select("select * from eval_targets")
List getEvalTargets();
//other code...
}
而目标ExtJS要consume的格式:
[quote]
{
evalTargets: [
{id: 1, "version": 0, "url": "http://www.tuniu.com/","md5": "856f509af96b3c68dccca042d6a21729", "xianlu_confidence" : 0.732410},
{id: 2, "version": 1, "url": "http://www.tuniu.com/","md5": "856f509af96b3c68dccca042d6a21729", "xianlu_confidence" : 0.932410}
],
totalCount: 2
}
[/quote]
这时候离ExtJS要consume的格式相差甚远。
我们定义VO来将数据展现,我们把EvalTarget的所有字段封装成一个evalFields,希望能接近我们目标ExtJS要consume的格式。
package com.qunar.search.evaltool.vo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.json.JSONException;
import org.json.JSONObject;
import com.qunar.search.evaltool.model.EvalTarget;
public class EvalTargetVO {
private Map evalFields;
public EvalTargetVO(EvalTarget evalTarget){
String evalJson = evalTarget.getEvalJson();
try {
evalFields = new HashMap();
evalFields.put("id", evalTarget.getId().toString());
evalFields.put("url", evalTarget.getUrl());
evalFields.put("version", evalTarget.getVersion().toString());
JSONObject jsonObject = new JSONObject(evalJson);
@SuppressWarnings("rawtypes")
Iterator it = jsonObject.keys();
while(it.hasNext()){
String key = it.next().toString();
String value = jsonObject.get(key).toString();
evalFields.put(key, value);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public Map getEvalFields() {
return evalFields;
}
}
在控制器中:
@RequestMapping(value="/list")
public @ResponseBody Map list(){
Map map = new HashMap();
List evalTargets = wrap2Vo(evalTargetService.getEvalTarget());
map.put("evalTargets", evalTargets);
return map;
}
这时候生成的JSON格式是这样的:
[quote]
{
evalTargets: [
{
evalFields: {id: 1, "version": 0, "url": "http://www.tuniu.com/","md5": "856f509af96b3c68dccca042d6a21729", "xianlu_confidence" : 0.732410 }
},
{
evalFields: {id: 2, "version": 1, "url": "http://www.tuniu.com/","md5": "856f509af96b3c68dccca042d6a21729", "xianlu_confidence" : 0.932410}
}
],
totalCount: 2
}
[/quote]
还是和目标有很大的差距,这时候就得用自定义Jackson的Serializer来解决这个格式问题了:
package com.qunar.search.evaltool.vo;
import java.io.IOException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializerProvider;
public class EvalTargetVOSerializer extends JsonSerializer{
@Override
public void serialize(EvalTargetVO value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(jgen, value.getEvalFields());
}
}
我们简单将EvalTargetVO的evalFields的hashmap使用ObjectMapper写入JsonGenerator即可转换成目标格式。
我们在使用注解来指定Json序列化为我们自定义个序列化类:
@JsonSerialize(using=EvalTargetVOSerializer.class)
public class EvalTargetVO
这样就解决了对于动态扩展字段提供ExtJs需要的Json格式的数据了。
Jackson Json的一些API以及例子:
http://wiki.fasterxml.com/JacksonInFiveMinutes