论坛首页 Web前端技术论坛

json 解析

浏览 3981 次
锁定老帖子 主题:json 解析
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-03-01  

看看别人写的json,自己研读一下,顺便做下笔记:

json解析和反解析主要的就是遍历和递归这个思路,

首先是json转成object,思路是:
1.通过chr=src.charCodeAt(nextPos++)这个来一次读取这个json版的String

2.然后通过对这个chr的类型做出不同的返回结果,

3.对这个返回结果做出不同的出来如:

    "{" 则开始创建object   直到出现"}" 

    "[" 开始穿件数组 "]"创建数组结束

 4.不论创建对象还是数组,获取下一个value都是通过nextValue()这个同样的方法,

进行处理,也就是进行递归,直到最后一个char

代码如下:

package com.depth.viewer.utils.json
{
	/**
	 * @example ActionScript to use JSONDecoder: 
	 * <listing version="3.0">
	 * var s:String=null;
	 * var jSONDecoder:JSONDecoder = new JSONDecoder(s);
	 * </listing>
	 *
	 **/
	
	public class JSONDecoder
	{
		
		private var value:Object;
		private var tokenizer:JSONTokenizer;
		private var token:JSONToken;
		
		public function JSONDecoder(s:String=null)
		{
			if(s!=null){
				this.tokenizer = new JSONTokenizer(s);
				this.nextToken1();
				this.value = this.parseValue();
				return;
			}
			
		}
		
		private var chr:int;

	    private var tok:int;
	
	    private var src:String;
	
	    private var lastPos:int;
	
	    private var nextPos:int;
	
	    private var cachedChr:Boolean;
	
	    private var cachedTok:Boolean;
	
	    
	
	    public function decode(str:String):* {
	
	        var val:*;
	
	        src=str;
	
	        nextPos=0;
	
	        cachedChr=false;
	
	        cachedTok=false;
	
	        val=nextValue();
	
	        if(nextToken()!=0xff)error("Expected end of input found "+flush());
	
	        return val;
	
	    }
	
	    
		/**
		 * 获取下一个字符,返回该字符的16进制值
		 * */
	    private function nextChar():int {
	
	        if(cachedChr){
	
	            cachedChr=false;
	
	            return chr;
	
	        }
	
	        return chr=src.charCodeAt(nextPos++);
	
	    }
	
		private function nextToken1() : JSONToken
		{
			var _token:* = this.tokenizer.getNextToken();
			this.token = this.tokenizer.getNextToken();
			return _token;
		}
	
	    private function nextToken():int {
	
	        if(cachedTok){
	
	            cachedTok=false;
	
	            return tok;
	
	        }
	
	        while(nextChar()==0x20||chr==0x09||isNewline(chr));
	
	        if(chr==0x2f){//char == "/"
	
	            if(nextChar()==0x2f){
	
	                while(!isNewline(nextChar())){
	
	                    if(chr==0x00)return tok=0xff;
	
	                }
	
	            }
	
	            else if(chr==0x2a){//char == "*"
	
	                while(true){
	
	                    if(nextChar()==0x2a){
	
	                        if(nextChar()==0x2f)break;
	
	                        else if(chr==0x2a)cachedChr=true;
	
	                    }
	
	                    if(chr==0x00)error("Find /* but cannot find */");
	
	                }
	
	            }
	
	            else error("Unkown token /"+String.fromCharCode(chr));
	
	            return nextToken();
	
	        }
	
	        lastPos=nextPos-1;
	
	        if(chr==0x22||chr==0x27)return tok=0xfc;// char == " " "||char == " ' "
	
	        if(chr==0x5d)return tok=0xfb;//char == "]"
	
	        if(chr==0x5b)return tok=0xfa;//char == "["
	
	        if(chr==0x7d)return tok=0xf9;//char == "}"
	
	        if(chr==0x7b)return tok=0xf8;//char == "{"
	
	        if(chr==0x2c)return tok=0xf6;//char == ","
	
	        if(chr==0x3a)return tok=0xf7;//char == ":"
	
	        if(chr==0x2b)return tok=0xf4;//char == "+"
	
	        if(chr==0x2d)return tok=0xf5;//char == "-"
	
	        if(chr==0x00)return tok=0xff;//char == "nul"
	
	        if(chr==0x2e){//char == "."
	
	            if(!isDigit(nextChar()))error("Find . but cannot find Digit");
	
	            return nextFraction();
	
	        }
	
	        if(isDigit(chr)){
	
	            if(chr==0x30){
	
	                if(nextChar()!=0x78&&chr!=0x58)cachedChr=true;
	
	                else{
	
	                    if(!isHex(nextChar()))error("Find 0x or 0X but cannot find HexDigit");
	
	                    while(isHex(nextChar()));
	
	                    return cache(0xfe);
	
	                }
	
	            }
	
	            while(true){
	
	                if(nextChar()==0x2e)return nextFraction();
	
	                if(chr==0x65||chr==0x45)return nextExponent();
	
	                if(!isDigit(chr))break;
	
	            }
	
	            return cache(0xfe);
	
	        }
	
	        
	
	        if(!isIdentifier(chr))error("Unkown token "+flush());
	
	        while(isIdentifier(nextChar()));
	
	        return cache(0xfd);
	
	    }
	
	    
	
	    private function nextValue():* {
	
	        if(nextToken()==0xfd){
	
	            var str:String=flush(1);
	
	            if(str=="NaN")return NaN;
	
	            if(str=="null")return null;
	
	            if(str=="true")return true;
	
	            if(str=="false")return false;
	
	            if(str=="Infinity")return Infinity;
	
	            if(str=="undefined")return undefined;
	
	            error("Unkown identifier "+str);
	
	        }
	
	        if(tok==0xf8){
	
	            var obj:Object={};
	
	            if(nextToken()!=0xf9){
	
	                cachedTok=true;
	
	                while (true){
	
	                    var key:String;
	
	                    if(nextToken()==0xfd)key=flush(1);
	
	                    else if(tok==0xfc)key=nextString();
	
	                    else error("Unexpected token "+flush());
	
	                    if(nextToken()==0xf7)obj[key]=nextValue();
	
	                    else error("Expected token : found "+flush());
	
	                    if(nextToken()==0xf9)break;
	
	                    if(tok!=0xf6)error("Expected token } or , found "+flush());
	
	                }
	
	            }
	
	            return obj;
	
	        }
	
	        if(tok==0xfa){
	
	            var arr:Array=[];
	
	            if(nextToken()!=0xfb){
	
	                var needComma:Boolean=false;
	
	                var index:int=0;
	
	                cachedTok=true;
	
	                while(true){
	
	                    if(nextToken()==0xfb)break;
	
	                    if(tok==0xf6){
	
	                        arr.length=++index;
	
	                        needComma=false;
	
	                    }
	
	                    else if(needComma)error("Expected token  ] or , found "+flush());
	
	                    else{
	
	                        needComma=true;
	
	                        cachedTok=true;
	
	                        arr[index]=nextValue();
	
	                    }
	
	                }
	
	            }
	
	            return arr;
	
	        }
	
	        if(tok==0xf5)return -nextValue();
	
	        if(tok==0xfc)return nextString();
	
	        if(tok==0xfe)return Number(flush(1));
	
	        if(tok==0xff)error("End of input was encountered");
	
	        if(tok!=0xf4)error("Unexpected token "+flush());
	
	        return nextValue();
	
	    }
	
	    
	
	    private function nextString():String {
	
	        lastPos=nextPos;
	
	        var str:String="";
	
	        var tag:int=chr;
	
	        while(nextChar()!=tag){
	
	            if(chr==0x00||isNewline(chr))error("Unclosed string");
	
	            if(chr==0x5c){
	
	                str+=flush(1);
	
	                lastPos+=2;
	
	                if(nextChar()==0x75||chr==0x78){
	
	                    var n:int=chr==0x75?4:2;
	
	                    while(n>0&&isHex(nextChar()))n--;
	
	                    if(n==0)str+=String.fromCharCode(parseInt(flush(),16));
	
	                    else nextPos=--lastPos;
	
	                }
	
	                else if(chr==0x6e)str+="\n";
	
	                else if(chr==0x72)str+="\r";
	
	                else if(chr==0x62)str+="\b";
	
	                else if(chr==0x66)str+="\f";
	
	                else if(chr==0x74)str+="\t";
	
	                else lastPos--;
	
	            }
	
	        }
	
	        return str+flush(1);
	
	    }
	
	    
		/**
		 * 获取这个小数
		 * */
	    private function nextFraction():int {
	
	        while(true){
	
	            if(nextChar()==0x65||chr==0x45)return nextExponent();
	
	            if(!isDigit(chr))break;
	
	        }
	
	        return cache(0xfe);
	
	    }
	
	    
	
	    private function nextExponent():int {
	
	        if(nextChar()!=0x2b&&chr!=0x2d)cachedChr=true;
	
	        if(!isDigit(nextChar()))error("Need digit after exponent");
	
	        while (isDigit(nextChar()));
	
	        return cache(0xfe);
	
	    }
	
	    
	
	    private function cache(token:int):int {
	
	        cachedChr=true;
	
	        return tok=token;
	
	    }
	
	    
	
	    private function flush(back:int=0):String {
	
	        return src.substring(lastPos,lastPos=nextPos-back);
	
	    }
	
	    
	
	    private function error(text:String):void {
	
	        throw new Error(text);
	
	    }
	
	    
	
	    private function isHex(c:int):Boolean {
	
	        return isDigit(c)||(c>0x60&&c<0x67)||(c>0x40&&c<0x47);
	
	    }
	
	    
		/**
		 * 判断是不是数字  c>0&&c<9
		 * */
	    private function isDigit(c:int):Boolean {
	
	        return c>0x2f&&c<0x3a;
	
	    }
	
	    
	
	    private function isNewline(c:int):Boolean {
	
	        return c==0x0a||c==0x0d;
	
	    }
	
	    
	
	    private function isIdentifier(c:int):Boolean {
	
	        if(isDigit(c))return true;
	
	        if(c>0x60&&c<0x7b)return true;
	
	        if(c>0x40&&c<0x5b)return true;
	
	        if(c==0x5f||c==0x24)return true;
	
	        if(c==0xd7||c==0xf7)return false;
	
	        if(c<0x00c0||c>0xfaff)return false;
	
	        if(c>0x00d6&&c<0x00d8)return false;
	
	        if(c>0x00f6&&c<0x00f8)return false;
	
	        if(c>0x1fff&&c<0x3040)return false;
	
	        if(c>0x318f&&c<0x3300)return false;
	
	        if(c>0x337f&&c<0x3400)return false;
	
	        if(c>0x3d2d&&c<0x4e00)return false;
	
	        if(c>0x9fff&&c<0xf900)return false;
	
	        return true;
	    }
		
		private function parseValue() : Object
		{
			if (this.token == null)
			{
				this.tokenizer.parseError("Unexpected end of input");
			}
			switch(this.token.type)
			{
				case JSONTokenType.LEFT_BRACE:
				{
					return this.parseObject();
				}
				case JSONTokenType.LEFT_BRACKET:
				{
					return this.parseArray();
				}
				case JSONTokenType.STRING:
				case JSONTokenType.NUMBER:
				case JSONTokenType.TRUE:
				case JSONTokenType.FALSE:
				case JSONTokenType.NULL:
				{
					return this.token.value;
				}
				default:
				{
					this.tokenizer.parseError("Unexpected " + this.token.value);
					break;
				}
			}
			return null;
		}
		
		private function parseObject() : Object
		{
			var _loc_2:String = null;
			var _loc_1:* = new Object();
			this.nextToken1();
			if (this.token.type == JSONTokenType.RIGHT_BRACE)
			{
				return _loc_1;
			}
			while (true)
			{
				
				if (this.token.type == JSONTokenType.STRING)
				{
					_loc_2 = String(this.token.value);
					this.nextToken1();
					if (this.token.type == JSONTokenType.COLON)
					{
						this.nextToken1();
						_loc_1[_loc_2] = this.parseValue();
						this.nextToken();
						if (this.token.type == JSONTokenType.RIGHT_BRACE)
						{
							return _loc_1;
						}
						if (this.token.type == JSONTokenType.COMMA)
						{
							this.nextToken1();
						}
						else
						{
							this.tokenizer.parseError("Expecting } or , but found " + this.token.value);
						}
					}
					else
					{
						this.tokenizer.parseError("Expecting : but found " + this.token.value);
					}
					continue;
				}
				this.tokenizer.parseError("Expecting string but found " + this.token.value);
			}
			return null;
		}
		
		public function getValue()
		{
			return this.value;
		}
		
		private function parseArray() : Array
		{
			var _loc_1:Array = [];
			this.nextToken1();
			if (this.token.type == JSONTokenType.RIGHT_BRACKET)
			{
				return _loc_1;
			}
			while (true)
			{
				
				_loc_1.push(this.parseValue());
				this.nextToken1();
				if (this.token.type == JSONTokenType.RIGHT_BRACKET)
				{
					return _loc_1;
				}
				if (this.token.type == JSONTokenType.COMMA)
				{
					this.nextToken1();
					continue;
				}
				this.tokenizer.parseError("Expecting ] or , but found " + this.token.value);
			}
			return null;
		}
	}
}

 下面是把objct转换为json,其实也是同意的思路

首先判断这个object的类型,如null,String等简单类型直接转换

如果是数组:

创建:"[" 然后拼接起来"]"

如果是Object

创建"{" 然后拼接起来"}"

下面是代码

package com.depth.viewer.utils.json
{
	public class JSONEncoder
	{
		public function JSONEncoder()
		{
		}
		private var unescapes:Object={"\b":"b","\f":"f","\n":"n","\r":"r","\t":"t"};

   		private var escapePtn:RegExp=/["\b\f\n\r\t\\]/g;//"

    	private var controlPtn:RegExp=/\x00-\x19/g;

    

	    public function encode(obj:*):String {
	
	        var str:String=null;
	
	        var bool:Boolean=false;
	
	        if(obj===null)return "null";
	
	        if(obj===undefined)return "undefined";
	
	        if(obj is String)return encodeString(obj);
	
	        if(obj is Array){
	
	            str="[";
	
	            for (var i:int=0,j:int=obj["length"];i<j;i++){
	
	                bool?(str+=","):(bool=true);
	
	                str+=encode(obj[i]);
	
	            }
	
	            return str+"]";
	
	        }
	
	        if(obj["constructor"]==Object){
	
	            str="{";
	
	            for (var k:String in obj){
	
	                bool?(str+=","):(bool=true);
	
	                str+=encodeString(k)+":"+encode(obj[k]);
	
	            }
	
	            return str+"}";
	
	        }
	
	        return obj;
	
	    }
	
	    
	
	    private function escapeRepl(...args):String {
	
	        return "\\"+(unescapes[args[0]]||args[0]);
	
	    }
	
	    
	
	    private function controlRepl(...args):String {
	
	        var hexCode:String=String(args[0]).charCodeAt(0).toString(16);
	
	        if (hexCode.length==1)hexCode="0"+hexCode;
	
	        return "\\x"+hexCode;
	
	    }
	
	    
	
	    private function encodeString(str:String):String {
	
	        str=str.replace(escapePtn,escapeRepl);
	
	        str=str.replace(controlPtn,controlRepl);
	
	        return "\""+str+"\"";
	
	    }
	}
}

 

 

 

   发表时间:2013-03-06  
常在Iteye混血到了不少的东西,虽然知道怎么拼但是嫌麻烦。感谢楼主!
0 请登录后投票
   发表时间:2013-03-07  
fashjson?
0 请登录后投票
论坛首页 Web前端技术版

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