本文仅作客观比较fastjson与jackson的性能测试,部分测试代码引自http://www.oschina.net/code/snippet_1156226_26432#44097 文中的方法,但是纠正了对于jackson的使用方式(需要写成单例先初始化,不要每次都new)。分别测试序列化1000,1万与10万次数据所花费的时间。
当然在此,如果大家发现文中的使用错误,也希望随时指出来帮助大家将优化做的更好。
测试代码均使用最新的jar包,而具体版本如下:
Jackson 2.x:
(这里仅测试Jackson2.x因为和1.x相比还是有些变化的,从包名就可以发现2.x变成com.fasterxml.jackson而不是1.x的org.codehaus.jackson希望大家注意区分)
jackson-annotations-2.4.1.jar
jackson-core-2.4.1.jar
jackson-databind-2.4.1.jar
fastjson
fastjson-1.1.41.jar
======================================================
------------------------------------以下为测试结果------------------------------
======================================================
预置条件1:循环1000次。
============序列化===========
序列化生成数据所用时间(秒):0.12
序列化Jackson所用时间(秒):0.077
序列化fastjson所用时间(秒):0.07
===========反序列化===========
反序列化生成数据所用时间(秒):0.095
反序列化Jackson所用时间(秒):0.114
反序列化fastjson所用时间(秒):0.149
-------------------------------------------------------------------------------------
预置条件2:循环10000次。
============序列化===========
序列化生成数据所用时间(秒):0.289
序列化Jackson所用时间(秒):0.281
序列化fastjson所用时间(秒):0.277
===========反序列化===========
反序列化生成数据所用时间(秒):0.344
反序列化Jackson所用时间(秒):0.416
反序列化fastjson所用时间(秒):0.445
-------------------------------------------------------------------------------------
预置条件3:循环100000次。
============序列化===========
序列化生成数据所用时间(秒):1.99
序列化Jackson所用时间(秒):0.855
序列化fastjson所用时间(秒):1.774
===========反序列化===========
反序列化生成数据所用时间(秒):2.69
反序列化Jackson所用时间(秒):1.33
反序列化fastjson所用时间(秒):1.606
以上对于10万条数据的测试可以看出jackson2.x在序列化上确实显现出了一些优势。
以下附代码(并附件打包):
/**
* 主测试类
*/
package com.test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
/**
*
* @author guoyongxiang
* Date: 2014-8-20
*/
public class JsonParseTest {
public static void main(String[] args) throws IOException {
System.out.println("============序列化===========");
Monitoring.begin();
List<Corp> list = new ArrayList<Corp>();
for (int i = 0; i < 100000; i++) {
list.add(fullObject(Corp.class));
}
Monitoring.end("序列化生成数据");
// 排除首次初始化差异
JacksonMapper.toJson(list.get(0));
Monitoring.begin();
jacksonSerialize(list);
Monitoring.end("序列化Jackson");
// 排除首次初始化差异
JSON.toJSONString(list.get(0));
Monitoring.begin();
fastjsonSerialize(list);
Monitoring.end("序列化fastjson");
System.out.println("===========反序列化===========");
List<String> jsonStrList = new ArrayList<String>();
for (Corp corp : list) {
String str = JacksonMapper.toJson(corp);
jsonStrList.add(str);
}
Monitoring.end("反序列化生成数据");
// 排除首次初始化差异
JacksonMapper.toObj(jsonStrList.get(0), Corp.class);
Monitoring.begin();
jacksonUnSerialize(jsonStrList);
Monitoring.end("反序列化Jackson");
// 排除首次初始化差异
JSON.parseObject(jsonStrList.get(0), Corp.class);
Monitoring.begin();
fastjsonUnSerialize(jsonStrList);
Monitoring.end("反序列化fastjson");
}
// ---------------------------------序列化---------------------------------
public static void jacksonSerialize(List<Corp> list) throws JsonProcessingException {
for (Corp corp : list) {
String str = JacksonMapper.toJson(corp);
}
}
public static void fastjsonSerialize(List<Corp> list) {
for (Corp corp : list) {
String str = JSON.toJSONString(corp);
}
}
// ---------------------------------反序列化---------------------------------
public static void jacksonUnSerialize(List<String> list) throws IOException {
for (String json : list) {
Corp corp = JacksonMapper.toObj(json, Corp.class);
}
}
public static void fastjsonUnSerialize(List<String> list) {
for (String json : list) {
Corp corp = JSON.parseObject(json, Corp.class);
}
}
/**
* 填充一个对象(一般用于测试)
*/
public static <T> T fullObject(Class<T> cl) {
T t = null;
try {
t = cl.newInstance();
Method methods[] = cl.getMethods();
for (Method method : methods) {
// 如果是set方法,进行随机数据的填充
if (method.getName().indexOf("set") == 0) {
Class<?> param = method.getParameterTypes()[0];
if (param.equals(String.class)) {
method.invoke(t, getRandomString(5));
} else if (param.equals(Short.class)) {
method.invoke(t, (short) new Random().nextInt(5));
} else if (param.equals(Float.class)) {
method.invoke(t, new Random().nextFloat());
} else if (param.equals(Double.class)) {
method.invoke(t, new Random().nextDouble());
} else if (param.equals(Integer.class)) {
method.invoke(t, new Random().nextInt(10));
} else if (param.equals(Long.class)) {
method.invoke(t, new Random().nextLong());
} else if (param.equals(Date.class)) {
method.invoke(t, new Date());
} else if (param.equals(Timestamp.class)) {
method.invoke(t, new Timestamp(System.currentTimeMillis()));
} else if (param.equals(java.sql.Date.class)) {
method.invoke(t, new java.sql.Date(System.currentTimeMillis()));
}
}
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return t;
}
public static String getRandomString(int length) { //length表示生成字符串的长度
String base = "abcdefghijklmnopqrstuvwxyz0123456789"; //生成字符串从此序列中取
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
}
计时器:
/**
*
*/
package com.test;
/**
* 计时器
* @author guoyongxiang
* Date: 2014-8-20
*/
public class Monitoring {
private static ThreadLocal<Long> begin = new ThreadLocal<Long>();
public static void begin() {
begin.set(System.currentTimeMillis());
}
public static void end(String name) {
double time = (System.currentTimeMillis() - begin.get()) / 1000.0;
System.out.println(name + "所用时间(秒):" + time);
}
}
测试对象
/**
*
*/
package com.test;
import java.sql.Timestamp;
/**
* 对象
* @author guoyongxiang
* Date: 2014-8-20
*/
public class Corp {
private Long uid;
private Integer corpGrade;
private Integer cityId;
private String name;
private String EName;
private String description;
private String zipCode;
private String tel;
private String fax;
private String EMail;
private Integer isEmailOpen;
private Integer EMailChecked;
private Timestamp regDateOnGov;
private String backroll;
private String address;
private String webStoreUrl;
private Integer isNew;
private Integer credit;
private Integer activeDegrees;
private Integer hits;
private Integer isHitsRecord;
private Timestamp regTimeOnZfa;
private Integer corpType;
private Integer corpMajorcategoryId;
private Integer businessRoleId;
private String keyword;
private Integer developState;
private String isAlert;
private Integer advMemState;
private Integer advStockState;
private Integer allianceState;
private Timestamp lastUpdateTime;
private Integer corpMajorcategoryId1;
private String keyword1;
private Long certificatePic;
private Integer isUpdateCharter;
private Integer currcount;
private Integer curronsale;
private Integer curronhot;
private Integer currniccount;
private Integer currniconsale;
private Integer currniconhot;
private String buyProducts;
private Integer isOpenShop;
private Integer state;
private String mainProduct;
private String advBrandIds;
private String feature;
private Integer category;
private Integer contactFlag;
private String fastPassage;
// 省略getter/setter
}
jackson 工具类(默认设置,过多设置会降低效率而且很明显,如识别json中的单引号等)
package com.test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* JacksonMapper
*
* @author guoyongxiang
*/
public class JacksonMapper {
private static final ObjectMapper mapper = new ObjectMapper();
private JacksonMapper() {
}
public static ObjectMapper getInstance() {
return mapper;
}
/**
* Object to Json String
*
* @param obj
* @return
* @throws JsonProcessingException
*/
public static String toJson(Object obj) throws JsonProcessingException {
ObjectMapper mapper = JacksonMapper.getInstance();
//SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
//mapper.setDateFormat(df);
return mapper.writeValueAsString(obj);
}
/**
* Json to List
*
* @param <T>
* @param json
* @param clazz
* @return
* @throws IOException
* @throws JsonMappingException
* @throws JsonParseException
*/
public static <T> List<T> toList(String json, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = JacksonMapper.getInstance();
//mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
//mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
List<T> list = mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz));
return list;
}
/**
* Json String to Object<br>
* String json = "..."; ObjectMapper mapper = JacksonMapper.getInstance();<br>
* YourBean bean = mapper.readValue(json, new YourBean().getClass());
*
* @param json
* @param clazz
* @return
* @throws IOException
* @throws JsonMappingException
* @throws JsonParseException
*/
public static <T> T toObj(String json, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException{
ObjectMapper mapper = JacksonMapper.getInstance();
//mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
//mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
return mapper.readValue(json, clazz);
}
/**
* JsonNode to Object
* @param node
* @param clazz
* @return
* @throws JsonParseException
* @throws JsonMappingException
* @throws IOException
*/
public static <T> T toObj(JsonNode node, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException{
ObjectMapper mapper = JacksonMapper.getInstance();
return mapper.readValue(node.toString(), clazz);
}
/**
* Json String to JsonNode
* @param json
* @return
* @throws JsonProcessingException
* @throws IOException
*/
public static JsonNode toNode(String json) throws JsonProcessingException, IOException{
ObjectMapper mapper = JacksonMapper.getInstance();
return mapper.readTree(json);
}
/**
* Object to JsonNode
* @param obj
* @return
* @throws JsonProcessingException
* @throws IOException
*/
public static JsonNode toNode(Object obj) throws JsonProcessingException, IOException{
String json = toJson(obj);
return toNode(json);
}
}