读Ext之十(解析JSON)

首先,回到第一篇。使用Ext.apply为Ext对象添加了一些属性,

1
2
3
4
5
Ext.apply(Ext, {
    ...
    USE_NATIVE_JSON : false,      
    ...     
});

USE_NATIVE_JSON 即为其中之一, 可以使用它来设置是否开启浏览器原始的JSON(即JSON.parse,JSON.stringify)来解析或反解析。这是ECMA5中加入的,在 字符串转换成JSON的三种方式中已经提到。

该值初始为false,即不开启。设置为true则开启如

Ext.USE_NATIVE_JSON = true;

Ext.util.JSON 内部定义了一些私有方法,对外公开的有三个方法

encodeDate 将日期对象转成字符串
encode     将JS对象转成字符串
decode     将字符串转成JS对象

此外,encode和decode分别赋值给了Ext.encode和Ext.decode。如

1
2
Ext.encode = Ext.util.JSON.encode;
Ext.decode = Ext.util.JSON.decode;

即开发时可以使用更简短的Ext.encode和Ext.decode而非冗长的Ext.util.JSON.encode和Ext.util.JSON.decode。

Ext.util.JSON的大体结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Ext.util.JSON = new (function(){
    var useHasOwn = !!{}.hasOwnProperty,
        isNative = function() {
            var useNative = null;
 
            return function() {
                if (useNative === null) {
                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
                }
         
                return useNative;
            };
        }(),
        ...
        ;
 
    this.encodeDate = function(o){
    };
    this.encode = function() {
 
    }();
    this.decode = function() {
 
    }();
 
})();

可看到new了一个匿名函数(类),即Ext.util.JSON为一个单体。

匿名类中定义了一些私有变量useHasOwn、isNative等,this上挂了三个方法,即上面提到的对外公开的三个接口方法。

isNative 函数用来判断是否开启浏览器原始解析JSON的API,当然该函数只在Ext.USE_NATIVE_JSON为true的时候起作用,否则永远使用私有的doDecode和doEncode来解析。

1
2
3
4
5
6
7
8
9
isNative = function() {
    var useNative = null;
    return function() {
        if (useNative === null) {
            useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
        }
        return useNative;
    };
}(),

pad 函数用来计算日期,所传参数n小于10时添加个0, 如月份传3时返回03,自动补个0。 this.encodeDate方法中用到。

1
2
3
pad = function(n) {
    return n < 10 ? "0" + n : n;
},

doDecode 函数将字符转成JS对象,这里采用eval方式,当然还可以使用new Function。

1
2
3
doDecode = function(json){
    return eval("(" + json + ')');   
},

别忘了eval中两旁的小括号,否则会有意想不到的bug。为何加小括号见:JavaScript中大括号“{}”的多义性 


doEncode 函数将JS对象转换成符合JSON规范的字符串,这个函数比较复杂。先对基本类型和数组,日期进行转换,最后是对JS对象的处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
doEncode = function(o){
    if(!Ext.isDefined(o) || o === null){
        return "null";
    }else if(Ext.isArray(o)){
        return encodeArray(o);
    }else if(Ext.isDate(o)){
        return Ext.util.JSON.encodeDate(o);
    }else if(Ext.isString(o)){
        return encodeString(o);
    }else if(typeof o == "number"){
        //don't use isNumber here, since finite checks happen inside isNumber
        return isFinite(o) ? String(o) : "null";
    }else if(Ext.isBoolean(o)){
        return String(o);
    }else {
        var a = ["{"], b, i, v;
        for (i in o) {
            // don't encode DOM objects
            if(!o.getElementsByTagName){
                if(!useHasOwn || o.hasOwnProperty(i)) {
                    v = o[i];
                    switch (typeof v) {
                    case "undefined":
                    case "function":
                    case "unknown":
                        break;
                    default:
                        if(b){
                            a.push(',');
                        }
                        a.push(doEncode(i), ":",
                                v === null ? "null" : doEncode(v));
                        b = true;
                    }
                }
            }
        }
        a.push("}");
        return a.join("");
    }   
},

doEncode中对字符串的转换用到了encodeString及encodeArray函数。

最后是三个挂在this上的方法,以this.decode示例

1
2
3
4
5
6
7
8
9
10
this.decode = function() {
    var dc;
    return function(json) {
        if (!dc) {
            // setup decoding function on first access
            dc = isNative() ? JSON.parse : doDecode;
        }
        return dc(json);
    };
}();

dc = isNative() ? JSON.parse : doDecode 可以看到如果isNative()返回true则使用浏览器原始的JSON.parse,否则使用doDecode。

 

 

posted on   snandy  阅读(12935)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
历史上的今天:
2011-05-01 JS Queue LazyLoad 之一
2011-05-01 JS/CSS module LazyLoad 之三
< 2012年5月 >
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9

统计

点击右上角即可分享
微信分享提示