精华帖 (2) :: 良好帖 (5) :: 新手帖 (0) :: 隐藏帖 (15)
|
|||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | ||||||||||||||||||
发表时间:2010-01-19
老实说,也不是没在JSON的表达样式上思考过,我在写测试用例时就推翻了不下两个版本
我现在初步的考虑是:先完成一个解析JSON的版本的解析器,通过不同call请求对不同协议的需求,无缝的实现XML和JSON的输入-》解析-》服务寻址-》调用-》解析-》输出的同样过程。 也就是说,我要求自己写的JSON实现,在相同的测试用例下要一摸一样,同时都能通过 所以在这个角度上说,可能不能发挥JSON的“精炼”的特点,当然这可能更多的针对输入,输出上应该对JSON会更友好些。 但无论如何,对用户都是友好的,透明的 |
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-01-21
我想到了’[‘字符。 经过努力,以下测试用例通过了: JSON:
测试用例代码:
到了测试hasMoreChildren的时候,正如JsonStandardStreamReader编写过程中所遇到的困难一样,困难又来了。 如何处理好层级关系,理顺’[‘和’]’字符的关系是重点。 重新审视了JSON表达式,决定再一次改版,如下: simpleCall:
callWithMap:
hasMoreChildren:
简洁多了吧,主要还是考虑JSON的层级关系,通过层级开始字符’[‘和层级关闭字符’]’,应该可以更好的处理hasMoreChildren接口。 还好,这样改动后对simpleCall和callWithMap测试用例没有任何影响,PASS。
|
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-01-21
最后修改:2010-01-21
经过两天的努力,终于攻克了各种难关,成功实现了所有测试用例的验证,核心方法如下: moveDown: public void moveDown() { int tag = parseTag(); switch(tag) { case TAG_METHOD: case TAG_INT: case TAG_LENGTH: case TAG_TYPE: case TAG_STRING: case TAG_BOOLEAN: case TAG_LONG: case TAG_DATE: case TAG_DOUBLE: case TAG_NULL: case TAG_REF: case TAG_LIST: case TAG_MAP: case TAG_CALL: currentTag = new Tag(tag, parseString()); stack.push(currentTag); depth++; break; default: throw new ProtocolException("unexpected tag: " + tagName(tag)); } }
moveUp:
public void moveUp() { int ch = skipWhitespace(); if (ch == '}'){ depth--; stack.pop(); currentTag = (Tag) stack.get(depth-1); }else if(ch == ']'){ depth--; stack.pop(); currentTag = (Tag) stack.get(depth-1); ch = skipWhitespace(); if (ch != '}') throw expectedChar("'}'", ch); }else throw expectedChar("'}' or ']'", ch); }
parseTag:
parseString:
所提供的测试用例包括标准的buffalo-call请求,以及其他通用的JSON格式,均能有效解析。 所提供的测试用例清单如下:
测试用例 说明 testSimpleCall 简单的buffalo-call testCallWithMap 带map的相对复杂的buffalo-call testHasMoreChildren 复杂的用以测试hasMoreChildren方法的buffalo-call testComplexTest 最复杂的混杂map/list/primitive的buffalo-call testPrimitive 非buffalo-call的标准的primitive格式的JSON testNull 非buffalo-call的标准的null格式的JSON testList 非buffalo-call的标准的list格式的JSON testChineseChar 非buffalo-call的标准的带中文字符的JSON
抱怨一下:javaeye的编辑器一旦带有代码,往往需要反复编辑多次才能成功,否则会被莫名其妙的截掉了,我不得不把所有注释都干掉了——也该改进了! |
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-01-21
最后修改:2010-01-21
net.buffalo.protocal.io.json.JsonStreamWriter
接下来就干这个了。 这个相对而言容易些,加上写JsonStreamWriter的经验,自然顺当些了。 原先提供的测试用例明显不足,也顺便完善了这块。 总体而言,花了个把小时开发和调试,整体就比较完善了,测试用例的思考和编写,反倒花费了更多的心思。 startNode:
public void startNode(String name) { if(isStart){ writer.write("["); stack.push("["); }else if(depth>0){ writer.write(","); } writer.write("{'"); writer.write(name); writer.write("':"); stack.push("{"); depth++; isStart = true; } endNode:
测试用例提供更为丰富的测试用例:
|
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-01-21
为了发布上面的这个回复,我老老实实的提交-》不行(都是缺胳膊少腿的)-》编辑了足足5遍!!
Robbin TX啊,这么牛气哄哄(回帖还需要考试)的网站,可不能被这个破编辑器给砸了呀 |
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-02-07
服务端的重构
考虑到在纳入SVN前完成重构,挤出点时间完成了重构。 所谓的重构,其实很简单,就是新增了两个抽象类方法,采用Template模式进行了抽象与具体的分离。 1、 AbstractStreamReader.java 2、 AbstractStreamWriter.java 这样,无论是JSON还是XML的IO实现,都变成了很简单,也更聚焦了。 类图如下:
OK,很简单的套路,但显然,具体协议实现代码变得非常的简单,可读性大大增加了。以后再出现什么阿猫阿狗协议,只要好的,你都可以遵照实现,难度大大降低咯。 |
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-02-08
前端JS其实服务端的重构是前段时间的事,也放到了SVN的分支(buffalo/branches/json)上了 近期杂事太多,耽搁了一下,但终于还是回到了前端。
老实说,我的前端架构、设计和开发能力要打折扣,但还是要硬着头皮上。 同样前端还是采用了TDD,基于script.aculo.us所提供的unittest.js做,还真的不错,不过实话说,咱还没干过js TDD,顺道学一把。 重点说说目标: 1、 平滑的实现兼容JSON协议的客户端; 2、 重构客户端脚本。 要说重点,主要还是一去一回:协议的封装和返回的解析。
call我的思路是:对外提供一致的接口,用类似于Factory模式的机制来做具体实现的生产和封装——js的OOP其实也是不错的,但我不是太会用,将就着先出一个beta版吧。
Buffalo.Call = Class.create(); Buffalo.Call.prototype = { initialize: function(methodname,protocol){ this.method = methodname; this.params = []; this.protocol = (protocol!=null && (protocol=='XML' || protocol=='JSON')) ? protocol : Buffalo.DefaultProtocol; }, addParameter: function(data){ if (typeof(data) == 'undefined') return; this.params[this.params.length] = data; }, toCall: function(){ return (this.protocol == 'JSON') ? this._json() : this._xml(); }, _xml: function(){ var s = "<buffalo-call>\n"; s += "<method>" + this.method+ "</method>\n"; for (var i = 0; i < this.params.length; i++) { var data = this.params[i]; var p = new Buffalo.XML(this, data); s += p.parseValue(data) + "\n"; } s += "</buffalo-call>"; return s; }, _json: function(){ //demo:[{'buffalo-call':[{'method':'divide'},{'double':1},{'double':2}]] var s = "[{'buffalo-call':[\n"; s += "{'method':'" + this.method+ "'}\n"; for (var i = 0; i < this.params.length; i++) { var data = this.params[i]; var p = new Buffalo.JSON(this, data); s += p.parseValue(data) + "\n"; } s += "]"; return s; }, getProtocol : function() { return this.protocol; } }
把原先在这里面的一些方法一分为二:一部分变成了具体的XML实现,一部分新建了一个Utils的Class。这些就略了,有兴趣自己down下来看。
json.js
下面是json.js的实现:
Buffalo.Reply = Class.create(); Buffalo.Reply.prototype = { initialize: function(xhr,protocol) { this._isFault = false; this._type = "null"; this._source = xhr.responseText; this._impl = (protocol == 'JSON') ? new Buffalo.Reply.JSON(xhr, this._source) : new Buffalo.Reply.XML(xhr, this._source); }, /** interface : getType, get the response object type */ getType: function() { return this._impl.getType(); }, /** interface : getResult, deserialize the response and return the javascript object */ getResult : function() { return this._impl.getResult(); }, /** interface : isFault, check response is fault or not */ isFault : function() { return this._impl.isFault(); }, /** interface : isFault, check response is null or not */ isNull: function() { return this._impl.isNull(); }, getSource : function() { return this._source; }, }
然后分别实现。后面的代码很多,就不贴了。 说实话,js的OOD/OOP也蛮有意思的,但一时半会儿还不顺手。
|
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||
发表时间:2010-03-10
Bug-fixed:net.buffalo.protocal.BuffaloProtocal.java
原先也提到取得BuffaloProtocal单例的时候会产生线程安全问题,其实能看的出来,为了慎重起见,还特意写了测试代码验证并得到确认。
最后进行了修复:
…… private static Map instanceMap = new HashMap(); …… public static BuffaloProtocal getInstance(String p){ BuffaloProtocal instance = (BuffaloProtocal) instanceMap.get(p); if (instance == null) { instance = new BuffaloProtocal(); instance.protocol = p; instanceMap.put(p, instance); } return instance; }
其实也很简单,用了一个Map,对XML和JSON各放了一个实例。
|
|||||||||||||||||||
返回顶楼 | |||||||||||||||||||