自定义Jackson Json的Serializer

转载请标明出处: http://fuliang.iteye.com/blogs/1141293

内容系统需要做分类、抽取等的评测工具,这个工具每次评测的对象需要的字段不一样,可以是一项或多项内容结合的评估。我们希望能够动态定义这些评测的字段,并且这些字段供给ExtJS的表格展现。
ExtJS所consume的JS格式非常固定,所以需要转化成这种固定的格式才能正确展现。所以我们对评估对象targets定义了几个固定的字段id,url,version和动态定义的评测字段evaljson的json字符串。

引用

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



这样我们写了模型:
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<EvalTarget> getEvalTargets();
       //other code...
}


而目标ExtJS要consume的格式:
引用

{
  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
}

这时候离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<String,String> evalFields;
	
	public EvalTargetVO(EvalTarget evalTarget){
		String evalJson = evalTarget.getEvalJson();
		try {
			evalFields = new HashMap<String,String>();

			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<String,String> getEvalFields() {
		return evalFields;
	}
}


在控制器中:
        @RequestMapping(value="/list")
	public @ResponseBody Map<String,Object> list(){
		Map<String,Object> map = new HashMap<String,Object>();
		List<EvalTargetVO> evalTargets = wrap2Vo(evalTargetService.getEvalTarget());
		map.put("evalTargets", evalTargets);
		return map;
	}

这时候生成的JSON格式是这样的:
引用

{
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
}

还是和目标有很大的差距,这时候就得用自定义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<EvalTargetVO>{

	@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

你可能感兴趣的:(java,json,ibatis,ExtJs)