精华帖 (0) :: 良好帖 (14) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2011-08-14
最后修改:2011-09-01
正式版已经发布: http://www.iteye.com/topic/1114250
由于工作上有json格式的数据需要处理, 需要一个json库, 但是网上的json库不是性能不好就是功能有限。 不得已逼自己动手写一个。 由于时间有限, 目前这个库只是用最基础的反射实现。 我打算分三个阶段完善这个jsonconvert库。 1、 json的框架与扩展性设计 2、 反序列化与序列化功能的优化 3、 性能优化,去掉反射改用asm 虽然目前是用反射实现的, 但是其性能已经不比其他json库差多少。 初期大部分时间花在框架与反序列化的设计上面。 实现细节方面没有下太多功夫。 现在将jsonconvert开源出来, 希望集思广益, 从网友那吸收更多的金点子~ : ) 先让大家看看jsonconvert的性能是个什么程度, 如果性能不好, 相信大家也不会再往下看了。 最近看到iteye上面有个fastjson库, 性能算是目前最快的, 下面是与fastjson简单的性能比较结果: (测试代码见附件) --------------------------NodeRecord----------------------------------- jsonconvert 循环解析单例10000次耗时: 786 fastjson 循环解析单例10000次耗时: 1466 jsonconvert 循环解析数组10000次耗时: 13403 fastjson 循环解析数组10000次耗时: 27020 ----------------------------------------------------------------------- jsonconvert 循环序列单例10000次耗时: 867 fastjson 循环序列单例10000次耗时: 809 jsonconvert 循环序列数组10000次耗时: 16270 fastjson 循环序列数组10000次耗时: 13830
--------------------------SimpleRecord----------------------------------- jsonconvert 循环解析单例10000次耗时: 349 fastjson 循环解析单例10000次耗时: 433 jsonconvert 循环解析数组10000次耗时: 3234 fastjson 循环解析数组10000次耗时: 6454 ------------------------------------------------------------------------- jsonconvert 循环序列单例10000次耗时: 240 fastjson 循环序列单例10000次耗时: 327 jsonconvert 循环序列数组10000次耗时: 3769 fastjson 循环序列数组10000次耗时: 3051
可以看出jsonconvert虽然是反射做的, 其性能已经不比fastjson差了。 而且如果测试的JavaBean内嵌层越多, 与fastjson的差距就会越大。 本来想用JDK7里面的InvokeDynamic替换反射, 但是考虑兼容JDK5、6,且以后始终会用asm代替, 所以没有使用, 简单的测试过InvokeDynamic,性能只是比反射快1-2倍而已,与直接调用的差距还是有一段滴。 下面介绍一下jsonconvert的功能。 普通对象只需要使用一个类JsonConvert, 该类只有三个方法:
public static String convertTo(Object value); public static <T> T convertFrom(String text, Class<T> clazz); public static <T> T[] convertArrayFrom(String text, Class<T> clazz);
简单介绍下jsonconvert的功能,目前默认支持的类型:
boolean -- double Boolean[]-- double[] String String[] Enum Enum[] Collection Map<String, ?> 树形循环引用(有空会重点介绍)
jsonconvert最大的特点是扩展性强。 含扩展类(有时间再写个详细的文档): JsonListener : 单个字段类(根据一个字符串值就可以转换成的对象) JsonObjectToken: 大对象类(以"{" 开头的对象) JsonObjectPrinter 序列化类
任何自定义的扩展都可以通过JsonFactroy 类进行注册:
public static <E> void register(Class<E> clazz, JsonListener<E> listener); public static <E> void register(Class<E> clazz, JsonObjectPrinter<E> printer); public static <E> void register(Class<E> clazz, JsonObjectCloner<? extends E> cloner); public static <E> void register(Class<E> clazz, Class<? extends JsonObjectToken<E>> token);
单个字段的简单配置可以通过JsonRef注解进行配置. @Inherited
@Documented @Target({METHOD}) @Retention(RUNTIME) public @interface JsonRef { //别名 String alias() default ""; //屏蔽getter boolean ignore() default false; /** * 只有当参数为Collection/Map才有效 * @return */ Class<?> type() default void.class; /** * 只有当参数为Collection/Map才有效 * @return */ Class<?> component() default void.class; }
这个类的nodes字段只是声明为List,解析的时候并不知道list的元素是什么类型,
所以需要显示的指明: 当然如果直接写明 public void setNodes(List<String>
nodes); 就无需JsonRef. List默认实例会使用ArrayList,
如果你想使用其他List的实现类需要JsonRef: 同理Map的默认实例用HashMap, Set的默认实例用HashSet, Queue、Deque的默认实例用LinkedList。 由于时间有限, 下面只简单介绍下JsonListener : Jsonconvert里面所有基础数据类型都是根据JsonListener 转换的。 大家可以看到很多java库里面都会把boolean、int、boolean[]、int[]、String 这些类进行特殊处理。 而jsonconvert里面秉着纯面向对象思想, 不会给boolean、int这些"异类"数据类型给予国企优待。与其他类型一视同仁。 库默认只实现了8个基本数值类型与String、枚举类。 很多其他常用类(如 Date, BigInteger, AtomicLong)并没有内置(后期可能会加上)。如果你当前有JavaBean的字段用到了Date类型, 你可以手工给jsonconvert注册Date的JsonListener:
JsonFactory.register(byte[].class, new JsonListener<byte[]>() { @Override public String convertTo(byte[] value) { if (value == null) return null; return JsonWriter.hexTo(value); } @Override public byte[] convertFrom(String value) { if (value == null) return null; return JsonWriter.hexFrom(value); } @Override public boolean quotable() { return true; } });
循环引用的简单例子:
public class Person { private String chname; private Person parent; private Person[] children; public static void main(String[] args) throws Throwable { Person grandpa = new Person(); grandpa.setChname("爷爷"); Person father = new Person(); father.setParent(grandpa); father.setChname("父亲"); Person uncle = new Person(); uncle.setParent(grandpa); uncle.setChname("叔叔"); Person son = new Person(); son.setParent(father); son.setChname("儿子"); Person gril = new Person(); gril.setParent(uncle); gril.setChname("堂妹"); grandpa.setChildren(new Person[]{father,uncle}); father.setChildren(new Person[]{son}); uncle.setChildren(new Person[]{gril}); String json = JsonConvert.convertTo(grandpa); System.out.println(json); System.out.println(JsonConvert.convertFrom(json, Person.class)); } /** -------setter getter-----**/ } 输出结果: {"children":[{"children":[{"chname":"儿子","parent":{"@":"@@@"}}],"chname":"父亲","parent":{"@":"@@@"}},{"children":[{"chname":"堂妹","parent":{"@":"@@@"}}],"chname":"叔叔","parent":{"@":"@@@"}}],"chname":"爷爷"} {"children":[{"children":[{"chname":"儿子","parent":{"@":"@@@"}}],"chname":"父亲","parent":{"@":"@@@"}},{"children":[{"chname":"堂妹","parent":{"@":"@@@"}}],"chname":"叔叔","parent":{"@":"@@@"}}],"chname":"爷爷"}
{'@':xxx} 就表示引用, {'@':'@'} 表示引用this, {'@':'@@'} 表示引用parent {'@':'@@@'} 表示parent.parent 依次类推; 之所以不用$这样的字符因为包括java在内很多语言的字段名都允许$字符。 后期可能支持{'@':'@@@.father'} 这种含字段名的格式。
jsonconvert库下载地址: http://tendon.googlecode.com/svn/trunk/tendon.jsonconvert/tags/0.1.0-beta2/
(待续)....
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-08-16
给LZ一个建议,弄几张图说明一下你的jsonListener等的一些内容。还有就是你的performance test最好代码放出来,好让大家知道比fastjson快在哪,还是你构造了一个有利于自己的环境而已
看lz的package应该是腾讯的吧,简单的过了下代码,代码还是蛮漂亮的。 1. 缺少单元测试 2. 缺少构建工具(用个maven,ant等,不然你让人家怎么导入eclipse工程) |
|
返回顶楼 | |
发表时间:2011-08-16
腾讯的和阿里的干上了,呵呵
|
|
返回顶楼 | |
发表时间:2011-08-16
icanfly 写道 腾讯的和阿里的干上了,呵呵
楼上的 不要误会, 纯属技术探讨, 不要扯上公司层面了, 我不是高层, 呵 如果我跟一个美国人争论, 你会不会说中国与美国干上了呢~ |
|
返回顶楼 | |
发表时间:2011-08-16
支持 有竞争才会有提升 最好国内领头的互联网公司 踊跃参与竞争 多搞些开源软件 进入百家争鸣 百花争妍 我们这些Coder就有福啦
|
|
返回顶楼 | |
发表时间:2011-08-16
这个怎么导入?什么构建?
|
|
返回顶楼 | |
发表时间:2011-08-16
nbzhang的代码还是有着当年的风格, 只是比以前要更加精炼,更加全面了。
|
|
返回顶楼 | |
发表时间:2011-08-16
kamhung 写道 icanfly 写道 腾讯的和阿里的干上了,呵呵
楼上的 不要误会, 纯属技术探讨, 不要扯上公司层面了, 我不是高层, 呵 如果我跟一个美国人争论, 你会不会说中国与美国干上了呢~ 我就没误会,是你太认真啦,大家都知道这是一个joke |
|
返回顶楼 | |
发表时间:2011-08-16
jin52yang 写道 这个怎么导入?什么构建?
下载源码自己建个工程就可以了, 现在很多人还是在用Eclipse, 本人用的Netbeans, 所以不提供工程文件, 因为每个人的IDE都不一样。 |
|
返回顶楼 | |
发表时间:2011-08-16
通过github.com/eishay/jvm-serializers/提供的测试程序,比fastjson还是慢不少的。
encode: alibaba-fastjson 2,262 tencent-convert 2,912 decode: alibaba-fastjson 1,528 tencent-convert 5,295 |
|
返回顶楼 | |