`
zcy860511
  • 浏览: 20296 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

自己写了一个JsonLib

阅读更多
自己写了一个Json的编码器和解码器
下面的地址是对比用的json-lib项目
http://json-lib.sourceforge.net/
下面是部分测试比较
/*
 * Copyright 2010 Sandy Zhang
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

/**
 * 
 */
package org.javazone.jroi.framework.coder;

import net.sf.json.JSONObject;

import org.javazone.jroi.framework.coder.json.JsonValue;
import org.javazone.jroi.framework.coder.json.encode.DefaultJsonEncoder;

/**
 * @author Sandy Zhang
 */
public class JsonTest
{
	public static void main(String[] args)
	{

		TestBean tb = null;
		DefaultJsonEncoder encoder = new DefaultJsonEncoder();
		for (int i = 0; i < 100; i++)
		{
			tb = new TestBean();
			JSONObject.fromObject(tb);
			encoder.encodeBean(tb).toJsonString();
		}
		int count = 10000;
		tb = tb.init();
		// 以上代码为预热代码

		double a = System.currentTimeMillis();
		for (int i = 0; i < count; i++)
		{
			JSONObject.fromObject(tb);
		}
		double c1 = System.currentTimeMillis() - a;
		// 以上为JSON_LIB编码。。。先不论其编码架构怎么样
		a = System.currentTimeMillis();
		for (int i = 0; i < count; i++)
		{
			new DefaultJsonEncoder().encodeBean(tb).toJsonString();
		}
		double c2 = System.currentTimeMillis() - a;
		// 以上为我自己写的Json_encoder
		System.out.println("test count = " + count);
		System.out.println("JSON ENCODER use time : " + c1 + " ms");
		System.out.println("JROI_JSON ENCODER use time : " + c2 + " ms");
		System.out.println("(JROI_JSON is faster than JSON_LIB)rate : "
				+ ((c1 / c2) - 1) * 100 + "%");
		System.out.println();
		// 下面是一次调用的微毫秒级别的比较
		a = System.nanoTime();
		JSONObject o1 = JSONObject.fromObject(tb);
		double c = System.nanoTime() - a;
		System.out.println("JSON_LIB run once use time " + c + " ns");
		a = System.nanoTime();
		JsonValue o2 = new DefaultJsonEncoder().encodeBean(tb);
		c = System.nanoTime() - a;
		System.out.println("JROI_JSON run once use time " + c + " ns");
	}
}

下面是测试结果
test count = 10
JSON ENCODER use time : 46.0 ms
JROI_JSON ENCODER use time : 16.0 ms
(JROI_JSON is faster than JSON_LIB)rate : 187.5%

JSON_LIB run once use time 2517448.0 ns
JROI_JSON run once use time 977297.0 ns

test count = 100
JSON ENCODER use time : 199.0 ms
JROI_JSON ENCODER use time : 93.0 ms
(JROI_JSON is faster than JSON_LIB)rate : 113.9784946236559%

JSON_LIB run once use time 731587.0 ns
JROI_JSON run once use time 517284.0 ns

test count = 1000
JSON ENCODER use time : 664.0 ms
JROI_JSON ENCODER use time : 663.0 ms
(JROI_JSON is faster than JSON_LIB)rate : 0.15082956259426794%

JSON_LIB run once use time 392889.0 ns
JROI_JSON run once use time 405821.0 ns

test count = 10000
JSON ENCODER use time : 4335.0 ms
JROI_JSON ENCODER use time : 6089.0 ms
(JROI_JSON is faster than JSON_LIB)rate : -28.806043685334203%

JSON_LIB run once use time 452007.0 ns
JROI_JSON run once use time 406438.0 ns

test count = 100000
JSON ENCODER use time : 42517.0 ms
JROI_JSON ENCODER use time : 71011.0 ms
(JROI_JSON is faster than JSON_LIB)rate : -40.126177634451%

JSON_LIB run once use time 389195.0 ns
JROI_JSON run once use time 516668.0 ns

首先,预热是相同的,应该不存在误差

因为我使用了许多对象,所以在大量创建对象的情况下,我的效率将被降低,因为JVM的垃圾回收机制
但是在一万次一下的比较中,我的编码程序占据优势,我相信很少情况有大于一千个对象被编码为Json字符串

比较客观的比较应该在100次比较的位置,我也尝试过编写简单的Bean进行测试,我的编码器同样占据速度上的优势,OK,我们看解码

我的结果是生成Map,然后通过接口传递到Handler中进行下一步处理,这样可以将算法与处理进行分离

/*
 * Copyright 2010 Sandy Zhang
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

/**
 * 
 */
package org.javazone.jroi.framework.coder;

import java.util.Map;

import net.sf.json.JSONObject;

import org.javazone.jroi.framework.coder.json.JsonObject;
import org.javazone.jroi.framework.coder.json.decode.analyze.AnalyzeEvent;
import org.javazone.jroi.framework.coder.json.decode.analyze.AnalyzeHandler;
import org.javazone.jroi.framework.coder.json.decode.analyze.JsonAnalyzer;

/**
 * @author Sandy Zhang
 */
public class DecodeTest
{
	public static class TestAnalyzeHandler
		implements AnalyzeHandler
	{

		@Override
		public void endAnalyze(AnalyzeEvent e)
		{
			// Map<String, Object> map = (Map<String, Object>) e.getResult();
			// System.out.println(map.get("name"));
			// Object[] objs = (Object[]) map.get("subBeans");
			// System.out.println(objs.length);
			// for (Object object : objs)
			// {
			// System.out.println(object);
			// }
		}

		@Override
		public void startAnalyze(AnalyzeEvent e)
		{
			// System.out.println("start");
		}
	}

	public static void main(String[] args)
	{
		for (int i = 0; i < 5; i++)
		{

			JsonAnalyzer analyzer = new JsonAnalyzer();
			analyzer.addAnalyzeHandler(new TestAnalyzeHandler());
			JsonEncoder encoder = Coder.newJsonEncoder();
			JsonObject jsonObj =
					(JsonObject) encoder.encodeBean(new TestBean().init());

			String jsonStr = jsonObj.toJsonString();
			JSONObject.fromObject(jsonStr);
			// System.out.println(jsonStr);
			analyzer.analyze(jsonStr);
		}
		// 预热代码
		int count = 10;

		JsonEncoder encoder = Coder.newJsonEncoder();
		JsonObject jsonObj =
				(JsonObject) encoder.encodeBean(new TestBean().init());

		String jsonStr = jsonObj.toJsonString();
		// 产生
		long a = System.currentTimeMillis();
		for (int i = 0; i < count; i++)
		{
			JsonAnalyzer analyzer = new JsonAnalyzer();
			analyzer.addAnalyzeHandler(new TestAnalyzeHandler());
			analyzer.analyze(jsonStr);
		}
		long b = System.currentTimeMillis();
		System.out.println(b - a);
		// 以上为我自己写的解码器

		a = System.currentTimeMillis();
		for (int i = 0; i < count; i++)
		{
			JSONObject.fromObject(jsonStr);
		}
		b = System.currentTimeMillis();
		System.out.println(b - a);
		// 以上为Json lib 解码方法
	}
}

这是10次的结果
21
102

这是100次的结果
139
467

这是1000次的结果
484
3450

这是10000次的结果
4217
39873

10万次,我不愿意比较了。。。。。。这个已经能够说明问题了。。

当然,不要指望net.sf.json.JSONObject工具会帮助你解码的很完善,fromObject出来的一样是map甚至是他自己创建的结构,并且不支持单一对象的编解码。
例如简单的字符串,比如我不发送对象,只是一个字符串,那么它就做不到,只会给你抛出一个异常。
不知道有人用这个工具包没有,至少我发现这个工具包很差,所以不得已自己写工具包

其次。。。也就是他的toBean方法,在处理泛型的时候不可能转换为确定的类型。

例如:TestBean里有一个List,装载的是SubBean,那么它不会很智能的给你转换为SubBean而是转换为了他自己的Bean,当你使用这个TestBean里的List的时候就等着java.lang.ClassCastException吧Orz.....

下面我把源码包发上来
----------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------
v1是最新版本

看来编程是白学了。。。居然有个BUG,大家如果愿意用的话帮我找找,看还有BUG没有,我已经审查了算法很多遍了。。。

下面是一个例子,怎么用的例子
package org.javazone.jroi.framework.coder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class TestBean
{

	private Collection<TestSubBean> beans = new ArrayList<TestSubBean>();

	public Collection<TestSubBean> getBeans()
	{
		return beans;
	}

	public void setBeans(Collection<TestSubBean> beans)
	{
		this.beans = beans;
	}

	public Set<TestSubBean> getTestSet()
	{
		return testSet;
	}

	public void setTestSet(Set<TestSubBean> testSet)
	{
		this.testSet = testSet;
	}

	public TestSubBean getTestSubBean()
	{
		return testSubBean;
	}

	public void setTestSubBean(TestSubBean testSubBean)
	{
		this.testSubBean = testSubBean;
	}

	public List<TestSubBean> getList()
	{
		return list;
	}

	public void setList(List<TestSubBean> list)
	{
		this.list = list;
	}

	private Set<TestSubBean> testSet = new HashSet<TestSubBean>();

	private TestSubBean testSubBean = new TestSubBean();

	private List<TestSubBean> list = new ArrayList<TestSubBean>();

	public TestBean init()
	{
		beans.add(new TestSubBean());
		testSet.add(new TestSubBean());
		list.add(new TestSubBean());
		return this;
	}

}

/*
 * Copyright 2010 Sandy Zhang
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

/**
 * 
 */
package org.javazone.jroi.framework.coder;

public class TestSubBean
{
	private static int currentid = 0;

	private String testString =
			"this is my sub bean : id = " + Integer.toString(++currentid);

	private String testNull = null;

	private Integer intTest = Integer.MAX_VALUE;

	private Long longTest = Long.MAX_VALUE;

	private Double doubleObjectTest = Double.MAX_VALUE;

	private Float floatObjectTest = Float.MAX_VALUE;

	public void setTestNull(String testNull)
	{
		this.testNull = testNull;
	}

	public String getTestNull()
	{
		return testNull;
	}

	public void setIntTest(Integer intTest)
	{
		this.intTest = intTest;
	}

	public Integer getIntTest()
	{
		return intTest;
	}

	public void setLongTest(Long longTest)
	{
		this.longTest = longTest;
	}

	public Long getLongTest()
	{
		return longTest;
	}

	public void setDoubleObjectTest(Double doubleObjectTest)
	{
		this.doubleObjectTest = doubleObjectTest;
	}

	public Double getDoubleObjectTest()
	{
		return doubleObjectTest;
	}

	public void setFloatObjectTest(Float floatObjectTest)
	{
		this.floatObjectTest = floatObjectTest;
	}

	public Float getFloatObjectTest()
	{
		return floatObjectTest;
	}

	public void setTestString(String testString)
	{
		this.testString = testString;
	}

	public String getTestString()
	{
		return testString;
	}

}

/*
 * Copyright 2010 Sandy Zhang
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

/**
 * 
 */
package org.javazone.jroi.framework.coder;

import java.util.Arrays;

/**
 * @author Sandy Zhang
 */
public class JsonTest
{
	public static void main(String[] args)
	{
		JsonEncoder encoder = Coder.newJsonEncoder();
		String jsonString = encoder.encodeBean(new TestBean().init()).toJsonString();
		System.out.println(jsonString);
		JsonDecoder decoder = Coder.newJsonDecoder();
		TestBean bean =
				(TestBean) decoder.decodeBean(jsonString, TestBean.class);
		System.out.println(bean.getTestSubBean().getTestNull());
		System.out.println(bean.getTestSubBean().getTestString());
		System.out.println(bean.getTestSubBean().getDoubleObjectTest());
		System.out.println(bean.getTestSubBean().getFloatObjectTest());
		System.out.println(bean.getTestSubBean().getIntTest());
		System.out.println(bean.getTestSubBean().getLongTest());
		System.out.println(Arrays.toString(bean.getList().toArray()));
		System.out.println(Arrays.toString(bean.getTestSet().toArray()));
		System.out.println(Arrays.toString(bean.getList().toArray()));

	}
}

{"beans":[{"longTest":9223372036854775807,"floatObjectTest":3.4028235E38,"intTest":2147483647,"testString":"this is my sub bean : id = 2","doubleObjectTest":1.7976931348623157E308,"testNull":null}],"testSubBean":{"longTest":9223372036854775807,"floatObjectTest":3.4028235E38,"intTest":2147483647,"testString":"this is my sub bean : id = 1","doubleObjectTest":1.7976931348623157E308,"testNull":null},"list":[{"longTest":9223372036854775807,"floatObjectTest":3.4028235E38,"intTest":2147483647,"testString":"this is my sub bean : id = 4","doubleObjectTest":1.7976931348623157E308,"testNull":null}],"testSet":[{"longTest":9223372036854775807,"floatObjectTest":3.4028235E38,"intTest":2147483647,"testString":"this is my sub bean : id = 3","doubleObjectTest":1.7976931348623157E308,"testNull":null}]}
null
this is my sub bean : id = 1
1.7976931348623157E308
3.4028235E38
2147483647
9223372036854775807
[org.javazone.jroi.framework.coder.TestSubBean@52fe85]
[org.javazone.jroi.framework.coder.TestSubBean@1e0cf70]
[org.javazone.jroi.framework.coder.TestSubBean@52fe85]


如果有大大愿意给小弟讲下架构就太好了。。。因为我最后发现最开始版本的Handler没用,我也考虑使用Builder模式在算法过程中使用Builder进行对象数组创建,但是都失败了,因为这个问题是个递归问题,递归在栈上不好做文章,确实要考虑就真的只有换非递归算法才能更好的使用设计模式里的算法分离了。。。。哎

至于效率,我也没测试了,看了jackson的实现后,我深深的自卑了
分享到:
评论
1 楼 zcy860511 2010-02-04  
沙发自己站,过两天,在完成了最后的Bean生成后,我将完善JAVADOC,并发放第一版

相关推荐

    JSON Java:Json-lib+依赖包+示例

    自己从Apache和SF整理得到的JSON-lib以及相应的依赖包。并且附加了几个自己写的代码示例

    json文件读写实例

    使用json-lib对json文件进行解析,自己做的实例,主要是写入json文件,包含五个jar包都在里面。

    ExtMVC+mysql +servlet+Json-lib实现用户的增删改查

    想学习ExtMVC实现的增删改查,去网上下载了个一看是坑爹的,根本不是程序,一气之下自己花了一下午写了这个完整的 ExtMVC+mysql +servlet+Json-lib实现用户的增删改查,供大家学习、指导

    dooringx-lib 提供自己的一套数据流事件机制以及弹窗等解决方案,可以让你更快地自己定制开发可视化拖拽平台

    dooringx-lib 在运行时维护一套数据流,主要分为json数据部分,左侧组件部分,右侧配置项部分,快捷键部分,弹窗部分,事件与函数部分,数据源部分。其除了提供基础的拖拽、移动、缩放、全选、旋转等功能外,还可以...

    spring2.0 struts2.0 hibernate3.0 开发的一个新闻系统

    系统内多处用到ajax技术,(自己写的json解析器,用prototype实现ajax请求).系统没有ui,还请原谅我不会作ui.请需要的人,自行添加.现在上传的工程的eclipse工程文件,请解压后放在eclipse的工程目录内即可,由于文件太大...

    一些自己用到的java包,详细内容见资源描述

    2、JSONArray_json-lib:里面包含使用JSONArray必须要用到的6个包,需要同时引入。 3、mysql连接.net(c#)和连接java的两个不同的连接包和驱动,看你写哪个了。.net的驱动在主界面。 4、sqljdbc:使用里面的jar7的jdbc...

    PM_MyBatis:Maven + MyBatis + servlet + EasyUI + Oracle完成的一个员工信息管理系统(初级)

    在使用MyBatis + servlet完成的人员信息管理系统中,我使用了一个net.sf.json的类来做json的数据,然后发现这个包只能使用jdk1.5的,所以我在pom文件中的依赖没有直接写网上的坐标,或者自己把jar包引入到lib下,...

    JAVA上百实例源码以及开源项目

     一个Java+ajax写的登录实例,附有JAVA源文件,JAVA新手朋友可以学习一下。 JAVA+JSP的聊天室 8个目标文件 简单 JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个...

    JAVA上百实例源码以及开源项目源代码

    数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写的...

    activesupport-taggedlogging-json

    将您的Ruby代码放在文件lib/activesupport/taggedlogging/json 。 要试验该代码,请运行bin/console进行交互式提示。 待办事项:删除此内容和上面的文字,并描述您的宝石 安装 将此行添加到您的应用程序的Gemfile...

    [SAX] json 解析支持库,可以静态编译-易语言

    回调函数写了例子,至于怎么使用到自己的项目中请在此基础上参考和扩展。 (原项目基于 LGPL-2.1,所以只是调用 lib 貌似不强制开源,vc 源码也没啥好保留的,就是懒得整理。。。 我编译了动态链接库,也调用它封装...

    java开源包1

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包11

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包2

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包3

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包6

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包5

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包10

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

    java开源包4

    fat32-lib 是一个用来读写 FAT 16/32 格式文件系统的纯 Java 类库(纯的)。 Eclipse的HTML格式化插件 Eclipse Tidy Eclipse HTML Tidy 是一款 Eclipse 的插件,用来对 HTML 文件内容进行清洗和格式化处理。它采用...

Global site tag (gtag.js) - Google Analytics