前言: 现在很流行前后分离,而我这里是完全的前后分离,后端只需要提供json数据给别人就行,无论是你的前端是开发c/s的还是app的.那么就经常会用到json转换器了,当然也可以凭借自己的能力直接去写一个.
- 目前我所知的四种json转换器:
1.json-lib
json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,包括commons-beanutils.jar,commons-collections-3.2.jar,commons-lang-2.6.jar,commons-logging-1.1.1.jar,ezmorph-1.0.6.jar,
对于复杂类型的转换,json-lib对于json转换成bean还有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。
json-lib在功能和性能上面都不能满足现在互联网化的需求。
2.开源的Jackson
相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。
而且Jackson社区相对比较活跃,更新速度也比较快。
Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。
Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式
3.Google的Gson
Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来,
但自从在2008年五月公开发布第一版后已被许多公司或用户应用。
Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。
而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。
类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。
Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。
4.阿里巴巴的FastJson
Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。
无依赖,不需要例外额外的jar,能够直接跑在JDK上。
FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。
FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。
综上4种Json技术的比较,在项目选型的时候可以使用Google的Gson和阿里巴巴的FastJson两种并行使用,
如果只是功能要求,没有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson将bean转换json确保数据的正确,使用FastJson将Json转换Bean
- 基本使用就不说了,百度很多
- 踩的坑
1.fastjson转换带泛型的类是可以的,但是需要带泛型的类提供无参构造
//pageInfo是com.github.pagehelper.PageHelper分页工具提供的类
PageInfo<xxx> pageInfo = JSON.parseObject(json,new TypeReference<PageInfo<xxxx>>(){});
运行后会报出:
翻译过来: 默认构造函数没找到
解决方案: 使用Gson来解析
2.使用Gson来转换带泛型的类
//pageInfo是com.github.pagehelper.PageHelper分页工具提供的类,
PageInfo<xxx> pageInfo = new Gson().fromJson(cacheValue, new TypeToken<PageInfo<ExchangeEntity>>() {
}.getType());
运行后报出:
一看就知道应该是日期转换的问题
解决方案: 手动注册一个适配器,将日期类型设置为长整型
解决代码:
GsonBuilder builder = new GsonBuilder();
// Register an adapter to manage the date types as long values
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonElement json, java.lang.reflect.Type arg1, JsonDeserializationContext arg2)
throws JsonParseException {
return new Date(json.getAsJsonPrimitive().getAsLong());
}
});
Gson gson = builder.create();
PageInfo<xxx> pageInfo = new Gson().fromJson(json, new TypeToken<PageInfo<xxx>>() {
}.getType());
3.用gson转换对象为json时出现缺失字段和空属性不转换的问题,经查询发现,Gson就是这种json转换的情况,如何解决?
这样可以实现序列化空值:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls(); //这个才是秘密
Gson gson = gsonBuilder.create();
4.今天程序中出现一个BUG,从缓存中读取字符串转List<对象>报错,发现是将List<对象>转JSON字符串的时候,日期出现问题了,Gson在处理Date格式时有个小陷阱,在不同环境中部署时可能会遇到问题。
Gson默认处理Date对象的序列化/反序列化是通过一个SimpleDateFormat对象来实现的,通过下面的代码去获取实例:
DateFormat.getDateTimeInstance()
在不同的locale环境中,这样获取到的SimpleDateFormat的模式字符串会不一样。
例如说,在我的开发机是Windows XP SP3,zh_CN.GBK,模式字符串是:
"yyyy-M-d H:mm:ss"
而在我们的一台测试服务器上,RHEL 5.4,en_US.UTF-8,模式字符串则是:
"MMM d, yyyy h:mm:ss a"
这就使得同样的Date对象通过Gson来序列化为JSON后内容不同。例如说要序列化的日期是2010-08-19 16:13:57,那么在我的开发机上得到的是:
"2010-8-19 16:13:57"
而在那台测试服务器上则是:
"Aug 19, 2010 4:13:57 PM"
这就……郁闷了。在一边序列化的内容在另一边会反序列化失败。
解决方案:
1.为了避免使用Gson时遇到locale影响Date格式的问题,使用GsonBuilder来创建Gson对象,在创建过程中调用GsonBuilder.setDateFormat(String)指定一个固定的格式即可。例如:
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.create();
2.使用JSONObject.toJSONString()方式来转为json字符串,这个JSONObject是属于fastJson中的一个类,它对于Date()类型是直接序列化为时间戳.这样配合Gson反序列化,相得益彰!
以后碰到了json转换相关的问题,会继续补充本帖,也欢迎大家来讨论,来指点我一下.