jackson 自定义解析类,处理复杂类型
2015-09-08 13:48
661 查看
本文简介
当jackson默认的解析方法不能成功将你的对象转换成json时,需要自定义解析器,去解决这个问题。可以自己转换成json,也可以把自己的对象转换成jackson能处理的对象。比如把 Multimap 转换成 Map。引出问题
jackson默认的解析方法基本够大多数我使用了,但是有时候会遇到有一些情况,它不能解析的。会得到结果{"empty":false},在这种情况下,我们需要自定义处理方法。
问题说明
我们知道Map是 key-value 类型的,如果一个Map<String,String>,这样子的话,多次put 同一个key,会覆盖掉前面的value,但是有些情况下我们需要多个value,这时我们会用到 google guava 包下面的 Multimap 类,这个类的value,默认是个集合,多次put会自动添加到value的集合中而不会覆盖。
但是在
SpringMVC框架中,
@ResponseBody的返回值是由
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter类处理的,这时会出现问题。
jackson默认不支持Multimap类,所以转换结果就是
{"empty":false},这并不是我们想要的。
解决方法
jackson中有注解@JsonSerialize,此注解中有两个值是我们需要使用的。使用方法如下:
public class Bean{ //处理List的泛型 @JsonSerialize(contentUsing = MultiMapSerializer.class) private List<Multimap> list; //处理属性本身 @JsonSerialize(using = MultiMapSerializer.class) private Multimap map; }
如上两种方法,一个是处理泛型,一个是处理属性。只需要添加在你的bean的属性上即可,另外需要再添加一个MultiMapSerializer类。
MultiMapSerializer类是参照 MapSerializer 实现的。
package com.util.jackson; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContainerSerializer; import com.google.common.collect.Multimap; import java.io.IOException; import java.util.Map; /** * 此类用于让jackson可以解析google guava 的 multimap, 而不至于出现 {"empty":false} 这样的结果 * 使用方法:在 Multimap的属性上添加 @JsonSerialize(using = MultiMapSerializer.class) * 在Multimap作为泛型的属性上(如List<Multimap>)添加 @JsonSerialize(contentUsing = MultiMapSerializer.class) * <p/> * Created by liuyibo on 15/9/8. * E-Mail:zhanlanstar@163.com */ public class MultiMapSerializer extends ContainerSerializer<Multimap<?, ?>> { public MultiMapSerializer() { super(Map.class, false); } @Override public JavaType getContentType() { return null; } @Override public JsonSerializer<?> getContentSerializer() { return null; } @Override public boolean isEmpty(Multimap<?, ?> value) { return false; } @Override public boolean hasSingleElement(Multimap<?, ?> value) { return false; } @Override protected ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) { return null; } @Override public void serialize(Multimap<?, ?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { //这里直接把value转换成map,jackson能处理map,交给它去处理 jgen.writeObject(value.asMap()); } }
在这个类里只需要写好构造函数,并在
serialize(Multimap<?, ?> value, JsonGenerator jgen, SerializerProvider provider)方法中写好处理方法就可以了。
处理方法有两种:一种是自己转换成json,写入到
JsonGenerator jgen对象中。
另一种是把自己的对象转换成jackson能处理的对象。
这里我使用第二种。
推荐使用第二种,可以避免发生不可预料的错误。
总结
写得好的代码,写得好的框架,或者工具,都是可扩展的。而可扩展的代码,在一开始看的时候总是会有各种各样不理解的东西出现在眼前。看得多了就能看懂了,但是最重要的还是要思考,看看别人怎么写的,如何能在自己的代码中,也可以实现轻松自如的扩展。可能一开始你的想法并不会被所有人理解,你要习惯,你要坚持,同时也要面对自己的错误,你会被别人认可的,只是并不会从一开始就会。
相关文章推荐
- GIT设置SSH公钥
- 坐标旋转(算法)
- 安卓的工程文件介绍
- QT之线程
- cocos2d-x lua c++ 相互调用代码中直接调用注册
- Linux expect 用法
- 小书匠语法手册
- 关于解决margin合并(折叠)的方法
- win2003 server 定时自动重启命令
- elasticsearch聚合--内存控制篇
- SQL中使用ESCAPE定义转义符
- 永久重定向
- matlab std函数 用法及实例
- EditPlus 编写运行 Groovy
- Delphi 2009
- sql server无法登陆问题
- 2014 iOS开发者收入调查报告(一):个人开发者篇
- 打印正/倒三角
- PEM文件
- 简单的curl提交数据