论坛首页 Web前端技术论坛

让Ajax框架Buffalo支持JSON协议而非仅仅自定义的XML协议[JS前端及单元测试完成]

浏览 7922 次
精华帖 (2) :: 良好帖 (5) :: 新手帖 (0) :: 隐藏帖 (15)
作者 正文
   发表时间:2010-01-17  
用不得改造那么累了,用我的beetle框架吧,其中基于web层ajax实现,通信协议用的就是json,可以实现java对象(包括列表等)与javascript对象透明转换,可以随意与当前流行的UI的js库整合。
0 请登录后投票
   发表时间:2010-01-18  
非常感谢楼上的推荐,昨天粗略看了下,你的beetle框架确实比较完整,值得学习,但个中的精华还没体会到,你可进一步开贴宣讲。

但我的目标不是简单的用AJAX框架,而是通过与原创作者沟通,结合自己的思考,学习和完善个人觉得比较精到的AJAX框架Buffalo
0 请登录后投票
   发表时间:2010-01-18  

经与Michael沟通,印证了我对于性能的猜想:

没错。如果用dom, 意味着使用通用的xml解析根据我的测试,当时使用最快的xpp3xml解析器都无法满足我的性能期待。

On 1 16, 2010 7:52 PM, "zhengxianquan" wrote:

Michael 

我已经开展了JSON协议的相关开发工作。

然而对照XML协议,我有个问题没想明白:为什么StreamReader要一个字符一个字符的解析,何不直接读出来后,直接转化为DOM再处理?

这其中难道有什么考虑吗?性能? 

对于JSON协议,在表达格式上有什么建议?

但正如我之前的考虑那样,我打算先做一次性读入->解析为JSONObject->再基于现有StreamReader接口实现系列方法的第一个版本,命名为JsonStandardStreamReader.java

然而,这个JsonStandardStreamReader.java只能是一个buffalo-call的实现,不具有原有XML协议下作为Reader的广泛通用性(可不限制于Buffalo):The Implementation is not a general JSON StreamReader, just for parsing buffalo-call only.”。

协议的表达格式经过多番测试验证,需要调整一下,举例如下:

[{'buffalo-call':''},{'method':'divide'},{'double':1},{'double':2}]

 

或者:

[{'buffalo-call':''},{'method':'sum'},{'int':1},{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'key2'},{'string':'value2'}]},{'string':test}]

 

基于TDD来做。目前的JsonStandardStreamReader已经可以解析上述的协议。

接下来将枚举各种buffalo-call的可能,尽可能的保证单元测试下的覆盖率。

0 请登录后投票
   发表时间:2010-01-18  
多年以后,一个贴子,引起我对Buffalo的回忆,感叹时光流逝,物是人非。。。
0 请登录后投票
   发表时间:2010-01-18  

net.buffalo.protocal.io.json.JsonStandardStreamReaderTest.java

第一个版本的测试用例,很长,但对buffalo-call具有较好的覆盖度:

package net.buffalo.protocal.io.json;

import java.io.StringReader;

import junit.framework.TestCase;
import net.buffalo.protocal.io.StreamReader;

/**
 * 
 * for json unit test
 * 
 * @author zhengxq
 * @see FastStreamReaderTest.java
 */
public class JsonStandardStreamReaderTest extends TestCase {
	private String simpleCall  = "[{'buffalo-call':''},{'method':'divide'},{'double':1},{'double':2}]";
	private String callWithMap = "[{'buffalo-call':''},{'method':'sum'}," +
									"{'int':1}," +
									"{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'key2'},{'string':'value2'}]}," +
									"{'string':test}" +
									"]";
	private String hasMoreChildren = "[{'buffalo-call':''},{'method':'sum'}," +
									 "{'int':1}," +
									 "{'map':[" +
									 " {'type':java.util.HashMap}," +
									 " {'string':'type'}," +
									 " {'string':'name'}," +
									 " {'list':[{'type':'list'},{'length':3}," +
									 "  {'string':a}," +
									 "  {'int':2}," +
									 "  {'double':8.88}]}," +
									 "]}]";
	private String complexTest = "[{'buffalo-call':''},{'method':'fullTypeTest'}," +
									 "{'boolean':1}," +
									 "{'date':20100118T154212Z}," +
									 "{'int':1}," +
									 "{'double':2.22},"+
									 "{'string':'Hello world'},"+
									 "{'list':["+
									 " {'type':''},"+
									 " {'length':2},"+
									 " {'int':100},"+
									 " {'string':hi}"+
									 " ]},"+
									 "{'map':[" +
									 " {'type':java.util.HashMap}," +
									 " {'string':key1}," +
									 " {'string':value1}," +
									 " {'string':key2}," +
									 " {'string':value2}," +
									 " {'string':java.util.ArrayList}," +
									 " {'list':[" +
									 "  {'type':''}," +
									 "  {'length':3}," +
									 "  {'int':1}," +
									 "  {'string':good}," +
									 "  {'string':baby}" +
									 " ]}" +
									 "]}," +
									 "{'double':3.33}" +
									 "]";	

	
	/* simpleCall */
	public void testSimpleCall() throws Exception {
		StringReader reader = new StringReader(simpleCall);
		StreamReader streamReader = new JsonStandardStreamReader(reader);
		assertEquals("buffalo-call",streamReader.getNodeName());
		streamReader.moveDown();
		assertEquals("method",streamReader.getNodeName());
		assertEquals("divide", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("double", streamReader.getNodeName());
		assertEquals("1", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("double", streamReader.getNodeName());
		assertEquals("2", streamReader.getValue());		
	}
	
	/* callWithMap */
	public void testShoudReadNested() throws Exception {
		StringReader reader = new StringReader(callWithMap);
		StreamReader streamReader = new JsonStandardStreamReader(reader);
		assertEquals("buffalo-call", streamReader.getNodeName());
		streamReader.moveDown();
		assertEquals("method", streamReader.getNodeName());
		assertEquals("sum", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("int", streamReader.getNodeName());
		assertEquals("1", streamReader.getValue());
		
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("map", streamReader.getNodeName());
		streamReader.moveDown();
		assertEquals("type", streamReader.getNodeName());
		assertEquals("java.util.HashMap", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("string", streamReader.getNodeName());
		assertEquals("key1", streamReader.getValue());		
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("string", streamReader.getNodeName());
		assertEquals("value1", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("string", streamReader.getNodeName());
		assertEquals("key2", streamReader.getValue());		
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("string", streamReader.getNodeName());
		assertEquals("value2", streamReader.getValue());
		
		streamReader.moveUp();
		streamReader.moveUp();
	}
	
	/* hasMoreChildren */
	public void testHasMoreChildren() throws Exception {
		StringReader reader = new StringReader(hasMoreChildren);
		StreamReader streamReader = new JsonStandardStreamReader(reader);
		assertTrue(streamReader.hasMoreChildren());
		streamReader.moveDown();
		//then {'method':'sum'}
		assertFalse(streamReader.hasMoreChildren());
		streamReader.moveUp();
		
		streamReader.moveDown();
		streamReader.moveUp();
		streamReader.moveDown();
		//then {'map':[...]}
		assertEquals("map",streamReader.getNodeName());
		assertTrue(streamReader.hasMoreChildren());
		
		streamReader.moveDown();
		//then {'type':java.util.HashMap}
		streamReader.moveUp();

		streamReader.moveDown();
		//then {'string':'type'}
		streamReader.moveUp();
		
		streamReader.moveDown();
		//then {'string':'name'}
		streamReader.moveUp();

		streamReader.moveDown();
		//then {'list':[...]}
		assertTrue(streamReader.hasMoreChildren());
		assertEquals("list",streamReader.getNodeName());
		
		while(streamReader.hasMoreChildren()) {
			streamReader.moveDown();
			streamReader.moveUp();
		}
		
		streamReader.moveUp();
		assertEquals("map",streamReader.getNodeName());
		
		assertFalse(streamReader.hasMoreChildren());
	}
	
	/**
	 *  more complex test.
	 *  //boolean、date、int、long、null、string、list、map、double
	 *  	var t1 = true;//
	 *  	var t2 = new Date();
	 *  	var t3 = 1;//int
	 *  	var t4 = parseFloat("2.22");
	 *  	//var t5 = null;
	 *  	var t6 = "Hello world";
	 *  	var t7 = [100,"hi"];//list
	 *  	var t8 = {'key1':'value1','key2':'value2','java.util.ArrayList':[1,"good","baby"]};//map
	 *  	var t9 = parseFloat("3.33");
	 *  
	 *  	buffalo.remoteCall("fullTypeService.fullTypeTest",[t1,t2,t3,t4,t6,t7,t8,t9], function(reply) {
	 *  		$("result").value = reply.getResult();
	 *  	},protocol)
	 *  @author zhengxq
	 */
	public void testComplexTest() throws Exception {
		StringReader reader = new StringReader(complexTest);
		StreamReader streamReader = new JsonStandardStreamReader(reader);
		assertEquals("buffalo-call",streamReader.getNodeName());
		assertTrue(streamReader.hasMoreChildren());
		streamReader.moveDown();
		//<method>fullTypeTest</method>
		assertEquals("method",streamReader.getNodeName());
		assertEquals("fullTypeTest",streamReader.getValue());
		assertFalse(streamReader.hasMoreChildren());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<boolean>1</boolean>
		assertEquals("boolean",streamReader.getNodeName());
		assertEquals("1",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<date>20100118T154212Z</date>
		assertEquals("date",streamReader.getNodeName());
		assertEquals("20100118T154212Z",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<int>1</int>
		assertEquals("int",streamReader.getNodeName());
		assertEquals("1",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<double>2.22</double>
		assertEquals("double",streamReader.getNodeName());
		assertEquals("2.22",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>Hello world</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("Hello world",streamReader.getValue());
		streamReader.moveUp();
		
		
		streamReader.moveDown();
		//<list>...</list>
		assertEquals("list",streamReader.getNodeName());
		assertTrue(streamReader.hasMoreChildren());
		
		streamReader.moveDown();
		//<type></type>
		assertEquals("type",streamReader.getNodeName());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<length>2</length>
		assertEquals("length",streamReader.getNodeName());
		assertEquals("2",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<int>100</int>
		assertEquals("int",streamReader.getNodeName());
		assertEquals("100",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>hi</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("hi",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveUp();//</list>

		streamReader.moveDown();
		//<map>...</map>
		assertEquals("map",streamReader.getNodeName());		
		assertTrue(streamReader.hasMoreChildren());
		
		streamReader.moveDown();
		//<type>java.util.HashMap</type>
		assertEquals("type",streamReader.getNodeName());
		assertEquals("java.util.HashMap",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>key1</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("key1",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>value1</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("value1",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>key2</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("key2",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>value2</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("value2",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>java.util.ArrayList</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("java.util.ArrayList",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<list>...</list>
		assertEquals("list",streamReader.getNodeName());
		assertTrue(streamReader.hasMoreChildren());
		
		streamReader.moveDown();
		//<type></type>
		assertEquals("type",streamReader.getNodeName());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<length>3</length>
		assertEquals("length",streamReader.getNodeName());
		assertEquals("3",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<int>1</int>
		assertEquals("int",streamReader.getNodeName());
		assertEquals("1",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>good</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("good",streamReader.getValue());
		streamReader.moveUp();
		
		streamReader.moveDown();
		//<string>baby</string>
		assertEquals("string",streamReader.getNodeName());
		assertEquals("baby",streamReader.getValue());
		streamReader.moveUp();
		//assertEquals("list",streamReader.getNodeName());
		
		streamReader.moveUp();//</list>
		assertEquals("map",streamReader.getNodeName());
		streamReader.moveUp();//</map>
		assertEquals("buffalo-call",streamReader.getNodeName());
		
		streamReader.moveDown();
		//<double>3.33</double>
		assertEquals("double",streamReader.getNodeName());
		assertEquals("3.33",streamReader.getValue());
		streamReader.moveUp();

		//assertEquals("buffalo-call",streamReader.getNodeName());		
		assertFalse(streamReader.hasMoreChildren());
	}
}

 

 

0 请登录后投票
   发表时间:2010-01-18  

net.buffalo.protocal.io.json.JsonStandardStreamReader

 

第一个版本仅用于解析buffalo-callJsonStandardStreamReader.java

package net.buffalo.protocal.io.json;

import java.io.IOException;
import java.io.Reader;
import java.util.Stack;

import net.buffalo.protocal.ProtocalTag;
import net.buffalo.protocal.ProtocolException;
import net.buffalo.protocal.io.StreamException;
import net.buffalo.protocal.io.StreamReader;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * The Implementation is not a general JSON StreamReader,
 * just for parsing buffalo-call only.
 * 
 * @author zhengxq
 * @see JsonStreamReader.java
 */
public class JsonStandardStreamReader implements StreamReader {
	private final Reader in;
	protected StringBuffer sbuf = new StringBuffer();
	private final JSONArray all;
	private final int len;	

	protected Stack stack  = new Stack();
	protected int depth = 0;
	
	protected Tag currentTag;
	private int pointer = 0;

	protected Stack paramStack  = new Stack();
	private int paramDepth = 0;
	private JSONArray param; //temp for map or list
	private int innerPointer = 0; //for map or list param
	
	protected JsonStandardStreamReader() {
		this.in = null;
		this.all = null;
		this.len = 0;
	}
	
	public JsonStandardStreamReader(Reader in){
		this.in = in;
		int ch;
		try {
			ch = readSingleChar();
			for (; ch > -1; ch = readSingleChar()) {
				sbuf.append((char)ch);
			}
		} catch (IOException e) {
			throw new StreamException(e);
		}
		try{
			all = new JSONArray(sbuf.toString());
			len = all.length();
		}catch(JSONException e){
			throw new ProtocolException("Invalid JSON String.");
		}
		moveDown();
	}

	/* move to next, and parse a Tag */
	public void moveDown() {
		JSONObject o = null;
		if(pointer==0){ // buffalo-call			
			try{
				o = all.getJSONObject(pointer);
				pointer++;
				if(o==null) throw new ProtocolException("The first tag should be 'buffalo-call'");				
			}catch(JSONException e){
				throw new ProtocolException("Invalid JSON String.");
			}catch(ProtocolException e){
				throw e;
			}
		}else if(pointer==1){ // method			
			try{
				o = all.getJSONObject(pointer);
				pointer++;
				if(o==null) throw new ProtocolException("The first tag should be 'method'");
			}catch(JSONException e){
				throw new ProtocolException("Invalid JSON String.");
			}
		}else{ // params
			try{
				//test for map or list
				Tag test = (Tag) stack.get(depth - 1);
				if(test.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
						|| test.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)) {
					//it's map, then get the inner object
					if(param == null){
						// reset it
						innerPointer = 0;	
						//parse it
						param = (JSONArray)test.value;
					}
					if(innerPointer>=param.length()) {
						//try to restore
						try{
							Param p = (Param) paramStack.pop();
							param = p.array;
							innerPointer = p.pointer;
						}catch(Exception e){
							throw new ProtocolException("JSONArray in the param is out of bound : len="+len+" but innerPointer="+innerPointer);
						}
					}
						
					o = (JSONObject) param.get(innerPointer);
					innerPointer++;
				}else{
					// reset it
					param = null;
					innerPointer = 0;					

					if(pointer >= len) 
						throw new ProtocolException("JSONArray is out of bound : len="+len+" but pointer="+pointer);
					o = all.getJSONObject(pointer);
					pointer++;
				}
			}catch(JSONException e){
				throw new ProtocolException("Unexcepted error.");
			}
		}
		parseTag(o);

		stack.push(currentTag);
		depth++;
		
		if(currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
				|| currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
			paramStack.push(new Param(param,innerPointer));
			param = (JSONArray)currentTag.value;
			innerPointer = 0;
		}
	}

	public void moveUp() {
		depth--;
		currentTag = (Tag) stack.pop();
		
		if(currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
				|| currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
			currentTag = (Tag) stack.get(depth-1);
			//restore it
			if(currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
					|| currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
				Param p = (Param) paramStack.pop();
				param = p.array;
				innerPointer = p.pointer;
			}
		}
	}
	
	/* get tag name from currentTag */
	public String getNodeName() {		
		return currentTag.tag;
	}

	/* get tag value from currentTag */
	public String getValue() {
		return String.valueOf(currentTag.value);
	}

	/* test if there has more*/
	public boolean hasMoreChildren() {
		//test for map or list
		Tag test = (Tag) stack.get(depth - 1);
		if(test.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
				|| test.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
			//it's map, then get the inner object
			if(param == null){
				//parse it
				param = (JSONArray)test.value;
			}
			if((innerPointer+1)<param.length()) return true;
		}else if(test.tag.equalsIgnoreCase(ProtocalTag.TAG_CALL)
				&& pointer<all.length()) return true;
		return false;
	}

	public void close() {
		try {
			in.close();
		} catch (IOException e) {
			throw new StreamException(e);
		}
	}
	
	protected int readSingleChar() throws IOException {
		return in.read();
	}
	
	// get value from a JSONObject, the key is a standard key
	private Tag parseTag(JSONObject o){
		Tag t = new Tag();
		for(int i=0; i < ProtocalTag.ALL_TYPED_TAGS.length; i++){
			try{
				t.tag = ProtocalTag.ALL_TYPED_TAGS[i];
				t.value = o.get(t.tag);					
				currentTag = t;
				return currentTag;
			}catch(JSONException e){}
		}
		return null;
	}
	
	class Tag {
		protected String tag;
		protected Object value;
		public Tag(){}
		public Tag(String tag, Object value) {
			this.tag = tag;
			this.value = value;
		}
	}
	
	class Param {
		protected JSONArray array;
		protected int pointer;
		public Param(JSONArray ja, int p) {
			this.array = ja;
			this.pointer = p;
		}
	}
}

 

毋庸置疑:It’s buggy :)

0 请登录后投票
   发表时间:2010-01-18  

net.buffalo.protocal.io.json.JsonStandardInputStreamReader

 

XML协议一样,完全是照葫芦画瓢的写了这个类:

package net.buffalo.protocal.io.json;

import java.io.IOException;
import java.io.InputStream;

import org.json.JSONArray;
import org.json.JSONException;

import net.buffalo.protocal.ProtocolException;
import net.buffalo.protocal.io.StreamException;
import net.buffalo.protocal.io.StreamReader;

/**
 * The same as FastInputStreamReader
 * 
 * @see FastInputStreamReader.java
 */
public class JsonStandardInputStreamReader extends JsonStandardStreamReader implements StreamReader {
	
	private final InputStream in;
	
	public JsonStandardInputStreamReader(InputStream in) {
		this.in = in;
		int ch;
		try {
			ch = readSingleChar();
			for (; ch > -1; ch = readSingleChar()) {
				sbuf.append((char)ch);
			}
		} catch (IOException e) {
			throw new StreamException(e);
		}
		try{
			all = new JSONArray(sbuf.toString());
			len = all.length();
		}catch(JSONException e){
			throw new ProtocolException("Invalid JSON String.");
		}
		moveDown();
	}

	public void close() {
		try {
			in.close();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	protected int readSingleChar() throws IOException {
		return in.read();
	}	
}

 

此时可以完整的测试了,且慢,Writer还没写呢,咋测试啊——简单了,我的JsonStreamWriter是拷贝XML协议的过来的,此时:

JSON-> JsonStandardInputStreamReader->调用服务-> JsonStreamWriter,哈哈,回写还是用原来的XML协议,怪是怪了点,但却是可以测试我的JsonStandardInputStreamReaderJSON协议的请求(Buffalo-Call),基本还好用的:

请求界面:



 

看日志,用了JSON协议,解析类是刚刚出炉的JsonStandardInputStreamReader



 

结果呢:



 

正确,YEAH!
 

  • 大小: 2.7 KB
  • 大小: 4 KB
  • 大小: 2.9 KB
0 请登录后投票
   发表时间:2010-01-18  

快速小结

 

 

上面版本的Reader,并非一个符合buffalo SteamReader接口的通用的JSON解析器,充其量只能是一个buffalo-call请求JSON的解析器而已。

另外,还是存在一些明显的问题的,且先不说性能,光就moveDownmoveUp逻辑的严谨性就够喝一壶。

 

其中,已知的BUG有

1、在单元测试用例testComplexTest中,我注释了两句assertEquals,因为他们测试是不能通过的,主要还是moveUp的逻辑可能还存在不完整不严谨。——当然了,一般人不会那么变态的moveUp后还要看看是啥。

2、存在一些“潜规则”硬编码。比如我假定了第一个JSONObject就是buffalo-call,第二个JSONObject就是method,第三个开始就是call方法的参数——虽然buffalo-call确实如此——这也就是为什么说这个Reader只能是一个buffalo-call请求JSON的解析器的根本原因。

 

但是,通过上面Reader的编写,让我更进一步了解了JSON的同时,也逐步尝试约定了JSON协议表达的约定。

 

总而言之,还是得写正宗的JsonStreamReader,绕不开啊。

 

0 请登录后投票
   发表时间:2010-01-19   最后修改:2010-01-19

net.buffalo.protocal.io.json.JsonStreamReader

 

 

正式写这个类了。

开始很顺利,对于如下简单的测试用例,很快就PASS了。

 

 

	private String simpleCall  = "[{'buffalo-call':''},{'method':'divide'},{'double':1},{'double':2}]";

	public void testSimpleCall() throws Exception {
		StringReader reader = new StringReader(simpleCall);
		StreamReader streamReader = new JsonStreamReader(reader);
		assertEquals("buffalo-call",streamReader.getNodeName());
		streamReader.moveDown();
		assertEquals("method",streamReader.getNodeName());
		assertEquals("divide", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("double", streamReader.getNodeName());
		assertEquals("1", streamReader.getValue());
		streamReader.moveUp();
		streamReader.moveDown();
		assertEquals("double", streamReader.getNodeName());
		assertEquals("2", streamReader.getValue());		
	}

 

然而对于复杂的参数,尤其是maplist这种存在复杂嵌套的部分,则暴露出了两个关键问题:

1moveUp/moveDown对于XML这种有明确封闭标签(如</double>)的,确实支持的非常好,但对于JSON却有些逻辑上的障碍:JSON不是特别方便/合适表达层级关系,也无特别的好用以匹配关闭的标签;

2JSON表达样式我所提供的是否适合Buffalo

我所提供的JSON表达样式,可参考JsonStandardStreamReaderTest.java

 

 

0 请登录后投票
   发表时间:2010-01-19  
这么写实现上没有问题,但感觉丢掉了JSON自带的类型支持。例如,对float, int, string, boolean等原生数据类型的支持,JSON是可以自描述的,而不用写上string:"abc", double: 1.0之类。

例如service.divide(1.0, 2.0), 我期待用JSON写起来应该是这样子的:

{buffalo-call: 'divide', parameters: [1.0, 2.0]}

例如Map的例子:

{buffalo-call: 'somemethod', parameters: [{id: 1, name: "Michael", gendor: true}, count: 2]}

这样写需要对json更加智能的处理。

你的实现仍然是没有问题的;只是这样写出来的协议对于xml没有本质的区别,对于客户端调用而言也没有太多的改善之处。
3 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics