Flash ActionScript JSON 的一个源代码

转自:http://blog.sina.com.cn/s/blog_7cf671ed0100qdc8.html
Source Code:
JSON.as
package framework.json {
    import flash.utils.describeType;

    public final class JSON {
        public static function encode(object:*):String {
            return new JSONEncoder(object).encode();
        }
       
        public static function decode(jsonString:String):* {
            return new JSONDecoder(jsonString).decode();
        }
       
        internal static const TYPE_ARRAY:String                = "Array";
        internal static const TYPE_BOOLEAN:String            = "Boolean";
        internal static const TYPE_DATE:String                = "Date";
        internal static const TYPE_NUMBER:String            = "Number";
        internal static const TYPE_INT:String                = "int";
        internal static const TYPE_UINT:String                = "uint";
        internal static const TYPE_STRING:String            = "String";
        internal static const VALUE_NULL:String                = "null";
        internal static const VALUE_TRUE:String                = "true";
        internal static const VALUE_FALSE:String            = "false";
        internal static const SYMBOL_LEFT_BRACE:String        = '{';
        internal static const SYMBOL_RIGHT_BRACE:String        = '}';
        internal static const SYMBOL_LEFT_BRACKET:String    = '[';
        internal static const SYMBOL_RIGHT_BRACKET:String    = ']';
        internal static const SYMBOL_COLON:String            = ':';
        internal static const SYMBOL_COMMA:String            = ',';
        internal static const SYMBOL_QUOTE:String            = '"';
        internal static const SYMBOL_T:String                = 't';
        internal static const SYMBOL_F:String                = 'f';
        internal static const SYMBOL_CLASS:String            = 'class';
        internal static const WRITE_ONLY_FLAG:String        = "writeonly";
       
        internal static function getProperties(o:Object):XMLList {
            var typeDescription:XML = describeType(o);
            return typeDescription..accessor.(@access != WRITE_ONLY_FLAG) + typeDescription..variable;
        }
       
        public function JSON(privateJSON:PrivateJSON) {}
    }
}

class PrivateJSON {}
JSONEncoder.as
package framework.json {
    import flash.utils.getQualifiedClassName;

    internal final class JSONEncoder {
        private var _obj:*;
       
        public function JSONEncoder(object:*) {
            _obj = object;
        }
       
        public function encode():String {
            var r:String;
            if (_obj is String)
                r = encodeString(_obj as String);
            else if (_obj is Number)
                r = encodeNumber(_obj as Number);
            else if (_obj is Date)
                r = encodeDate(_obj as Date);
            else if (_obj is Boolean)
                r = encodeBoolean(_obj as Boolean);
            else if (_obj is Array)
                r = encodeArray(_obj as Array);
            else if (_obj is Object)
                r = encodeObject(_obj);
            else
                r = JSON.VALUE_NULL;
            return r;
        }
       
        private function encodeString(s:String):String {
            return  JSON.SYMBOL_QUOTE + escape(s) + JSON.SYMBOL_QUOTE;
        }
       
        private function encodeNumber(n:Number):String {
            return isFinite(n) ? n.toString() : JSON.VALUE_NULL;
        }
       
        private function encodeBoolean(b:Boolean):String {
            return b ? JSON.VALUE_TRUE : JSON.VALUE_FALSE;
        }
       
        private function encodeDate(d:Date):String {
            return d.getTime().toString();
        }
       
        private function encodeArray(a:Array):String {
            var r:String = JSON.SYMBOL_LEFT_BRACKET;
            if (a.length > 0) {
                for each (var v:* in a) {
                    if (v != null) {
                        if (v is String)
                            r += encodeString(v as String);
                        else if (v is Number)
                            r += encodeNumber(v as Number);
                        else if (v is Date)
                            r += encodeDate(v as Date);
                        else if (v is Boolean)
                            r += encodeBoolean(v as Boolean);
                        else if (v is Array)
                            r += encodeArray(v as Array);
                        else
                            r += encodeObject(v);
                        r += JSON.SYMBOL_COMMA;
                    }
                }
                r = r.substr(0, r.length - 1);
            }
            return r + JSON.SYMBOL_RIGHT_BRACKET;
        }
       
        private function encodeObject(o:Object):String {
            var r:String = JSON.SYMBOL_LEFT_BRACE + JSON.SYMBOL_QUOTE + JSON.SYMBOL_CLASS + JSON.SYMBOL_QUOTE + JSON.SYMBOL_COLON + JSON.SYMBOL_QUOTE + escape(getQualifiedClassName(o).replace("::", ".")) + JSON.SYMBOL_QUOTE + JSON.SYMBOL_COMMA;
            var properties:XMLList = JSON.getProperties(o);
            var propertyName:String;
            var propertyType:String;
            var propertyValue:*;
            for each (var property:XML in properties) {
                propertyName = property.@name;
                propertyType = property.@type;
                propertyValue = o[propertyName];
                r += JSON.SYMBOL_QUOTE;
                r += propertyName;
                r += JSON.SYMBOL_QUOTE;
                r += JSON.SYMBOL_COLON;
               
                if (propertyValue == null)
                    r += JSON.VALUE_NULL;
                else {
                    if (propertyType == JSON.TYPE_STRING)
                        r += encodeString(propertyValue as String);
                    else if ((propertyType == JSON.TYPE_NUMBER) || (propertyType == JSON.TYPE_INT) || (propertyType == JSON.TYPE_UINT))
                        r += encodeNumber(propertyValue as Number);
                    else if (propertyType == JSON.TYPE_DATE)
                        r += encodeDate(propertyValue as Date);
                    else if (propertyType == JSON.TYPE_BOOLEAN)
                        r += encodeBoolean(propertyValue as Boolean);
                    else if (propertyType == JSON.TYPE_ARRAY)
                        r += encodeArray(propertyValue as Array);
                    else
                        r += encodeObject(propertyValue);
                }
                r += JSON.SYMBOL_COMMA;
            }
            return r.substr(0, r.length - 1) + JSON.SYMBOL_RIGHT_BRACE;
        }
    }
}
JSONDecoder.as
package framework.json {
    import flash.utils.getDefinitionByName;

    internal final class JSONDecoder {
        private var _jsonString:String;
        private var _jsonLength:int;
        private var _position:int;
        private var _currentChar:String;
       
        public function JSONDecoder(jsonString:String) {
            _jsonString = jsonString;
            _jsonLength = jsonString.length;
            _position = 0;
            nextChar();
            skipWhiteSpace();
        }
       
        public function decode():* {
            var s:String;
            var r:Object;
            switch(_currentChar) {
                case JSON.SYMBOL_LEFT_BRACE:
                    r = parseObject();
                    break;
                case JSON.SYMBOL_LEFT_BRACKET:
                    r = parseArray();
                    break;
                case JSON.SYMBOL_T:
                case JSON.SYMBOL_F:
                    r = parseBoolean();
                    break;
                case JSON.SYMBOL_QUOTE:
                    r = parseString();
                    break;
                default:
                    r = parseNumber();
            }
            if (r != null)
                r = convert(r);
            return r;
        }
       
        private function parseObject():Object {
            var r:Object = new Object();
            var n:String;
            var i:int;
            nextChar();
            while (!(_currentChar == JSON.SYMBOL_RIGHT_BRACE || _position >= _jsonLength)) {
                n = "";
                while (_currentChar != JSON.SYMBOL_COLON) {
                    if (_currentChar == JSON.SYMBOL_RIGHT_BRACE || _position >= _jsonLength) {
                        nextChar();
                        return r;
                    }
                    n += _currentChar;
                    nextChar();
                }
                if ((i = n.lastIndexOf(JSON.SYMBOL_COMMA)) != -1)
                    n = n.substr(i + 1);
                n = fixPropertyName(n);
                nextChar();
                skipWhiteSpace();
                switch (_currentChar) {
                    case JSON.SYMBOL_QUOTE:
                        r[n] = parseString();
                        break;
                    case JSON.SYMBOL_T:
                    case JSON.SYMBOL_F:
                        r[n] = parseBoolean();
                        break;
                    case JSON.SYMBOL_LEFT_BRACKET:
                        r[n] = parseArray();
                        break;
                    case JSON.SYMBOL_LEFT_BRACE:
                        r[n] = parseObject();
                        break;
                    case JSON.SYMBOL_COMMA:
                        r[n] = null;
                        break;
                    default:
                        r[n] = parseNumber();
                }
            }
            nextChar();
            return r;
        }
       
        private function parseArray():Array {
            var r:Array = new Array();
            nextChar();
            while (!(_currentChar == JSON.SYMBOL_RIGHT_BRACKET || _position >= _jsonLength)) {
                switch (_currentChar) {
                    case JSON.SYMBOL_QUOTE:
                        r.push(parseString());
                        break;
                    case JSON.SYMBOL_T:
                    case JSON.SYMBOL_F:
                        r.push(parseBoolean());
                        break;
                    case JSON.SYMBOL_LEFT_BRACKET:
                        r.push(parseArray());
                        break;
                    case JSON.SYMBOL_LEFT_BRACE:
                        r.push(parseObject());
                        break;
                    default:
                        r.push(parseNumber());
                }
                while (_currentChar != JSON.SYMBOL_COMMA) {
                    if (_currentChar == JSON.SYMBOL_RIGHT_BRACKET ||  _position >= _jsonLength) {
                        nextChar();
                        return r;
                    }
                    nextChar();
                }
                nextChar();
                skipWhiteSpace();
            }
            nextChar();
            return r;
        }
       
        private function parseNumber():Object {
            var r:Object;
            if (isDigit(_currentChar) || _currentChar == '-')
                r = readNumber();
            return r;
        }
       
        private function parseBoolean():Object {
            var r:Object;
            var s:String = _currentChar + nextChar() + nextChar() + nextChar();
            if (s == JSON.VALUE_TRUE)
                r = Boolean(true);
            else {
                s += nextChar();
                if (s == JSON.VALUE_FALSE)
                    r = Boolean(false);
            }
            return r;
        }
       
        private function parseString():Object {
            var r:Object;
            var idx:int = _jsonString.indexOf(JSON.SYMBOL_QUOTE, _position);
            if (idx == -1)
                _position = _jsonLength;
            else {
                r = (_jsonString.substring(_position, idx));
                _position = idx + 1;
            }
            nextChar();
            return r;
        }
       
        private function nextChar():String {
            return _currentChar = _jsonString.charAt(_position++);
        }
       
        private function skipWhiteSpace():void {
            while ((_currentChar == ' ') || (_currentChar == '\t') || (_currentChar == '\n') || (_currentChar == '\r')) {
                nextChar();
                if (_position >= _jsonLength)
                    break;
            }
        }
       
        private function readNumber():Object {
            var s:String = "";
            if (_currentChar == '-') {
                s += _currentChar;
                nextChar();
            }
            if (!isDigit(_currentChar)) return null;
            if (_currentChar == '0') {
                s += _currentChar;
                nextChar();
                if (isDigit(_currentChar)) return null;
            } else {
                while (isDigit(_currentChar)) {
                    s += _currentChar;
                    nextChar();
                }
            }
            if (_currentChar == '.') {
                s += _currentChar;
                nextChar();
                if (!isDigit(_currentChar)) return null;
                while (isDigit(_currentChar)) {
                    s += _currentChar;
                    nextChar();
                }
            }
            if (_currentChar == 'e' || _currentChar == 'E') {
                s += _currentChar;
                nextChar();
                if (_currentChar == '+' || _currentChar == '-') {
                    s += _currentChar;
                    nextChar();
                    if (!isDigit(_currentChar)) return null;
                    while (isDigit(_currentChar)) {
                        s += _currentChar;
                        nextChar();
                    }
                }
            }
            return Number(s);
        }
       
        private static function isDigit(ch:String):Boolean {
            return ( ch >= '0' && ch <= '9' );
        }
       
        private static function fixPropertyName(name:String):String {
            var r:String = "";
            var s:String;
            var loops:int = name.length;
            for (var i:int = 0; i < loops; i++) {
                s = name.charAt(i);
                if (!((s == ' ') || (s == '\t') || (s == '\n') || (s == '\r') || (s == '"') || (s == '\'')))
                    r += s;
            }
            return r;
        }
       
        private static function convertArray(a:Array):Array {
            var r:Array = new Array();
            for each (var e:* in a) {
                if ((e is String) || (e is Number) || (e is Date) || (e is Boolean))
                    r.push(e);
                else if (e is Array)
                    r.push(convertArray(e));
                else if (e is Object)
                    r.push(convertObject(e));
            }
            return r;
        }
       
        private static function convertObject(obj:Object):* {
            var r:Object;
            var clsName:String = obj[JSON.SYMBOL_CLASS];
            if (clsName != null) {
                try {
                    var clazz:Class = getDefinitionByName((clsName)) as Class;
                    var o:Object = new clazz();
                    var properties:XMLList = JSON.getProperties(o);
                    var propertyName:String;
                    var propertyType:String;
                    var propertyValue:*;
                    var dateProperty:Date;
                    for each (var property:XML in properties) {
                        propertyName = property.@name;
                        propertyType = property.@type;
                        propertyValue = obj[propertyName];
                        if ((propertyType == JSON.TYPE_STRING) ||
                            (propertyType == JSON.TYPE_NUMBER) ||
                            (propertyType == JSON.TYPE_INT) ||
                            (propertyType == JSON.TYPE_UINT) ||
                            (propertyType == JSON.TYPE_BOOLEAN)) {
                            o[propertyName] = propertyValue;
                        } else if (propertyType == JSON.TYPE_DATE) {
                            dateProperty = new Date();
                            dateProperty.setTime(propertyValue);
                            o[propertyName] = dateProperty;
                        } else if (propertyType == JSON.TYPE_ARRAY) {
                            if (propertyValue != null)
                                o[propertyName] = convertArray(propertyValue);
                        } else {
                            if (propertyValue != null)
                                o[propertyName] = convertObject(propertyValue);
                        }
                    }
                    r = o;
                } catch (e:Error) {
                    trace(e);
                }
            } else
                r = obj;
            return r;
        }
       
        private static function convert(obj:Object):* {
            var r:Object;
            if ((obj is String) || (obj is Number) || (obj is Date) || (obj is Boolean))
                r = obj;
            else if (obj is Array)
                r = convertArray(obj as Array);
            else if (obj is Object)
                r = convertObject(obj);
            else
                r = obj;
            return r;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值