非常教程

JSON教程

JSON解析

JavaScript 解析Json字符串的性能比较分析代码

我们在使用AJAX来做服务器端和客户端交互的时候,一般的做法是让服务器端返回一段JSON字符串,然后在客户端把它解析成JavaScript对象。

解析时用到的方法一般是eval或者new function,而目前IE8和Firefox3.1又内置了原生的JSON对象(据说会有一定的性能提升)。那我们在实际使用的时候怎样从这三种方法(因为性能问题,不考虑用javascript实现的解析)里面来选择呢?面对众多的浏览器,哪种方式的性能是最好的呢? 

一、测试方法 

1、首先指定测试次数及JSON字符串 

代码如下:

var count = 10000,
    o = null,
    i = 0,
    jsonString = '{"value":{"items": [{"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}';

2、循环解析并记录时间

eval 解析

代码如下:

var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = eval( "(" + jsonString + ")" ); 
} 
Console.output( "eval:" + ( new Date() - beginTime ) ); 

new Function 函数解析

代码如下:

var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = new Function( "return " + jsonString )(); 
} 
Console.output( "new Function:" + ( new Date() - beginTime ) ); 

native 原生解析

代码如下:

if ( typeof JSON !== "undefined" ) { 
var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); } 
Console.output( "native:" + ( new Date() - beginTime ) ); 
} else { 
Console.output( "native:not support!" ); 
} 

二、测试对象 

选择目前主流的浏览器(不考虑Maxthon一类的外壳),包括IE6、7、8,Firefox2、3、3.1,Chrome,Opera及Safari3、4。 

三、测试环境

T9300 CPU + 4G RAM + Windows2003,其中IE8使用的是Vista的环境,IE7在另外一台工作机(2G CPU + 2G RAM + Windows2003),考虑到主要是测试浏览器客户端的性能,结果的误差应该能够接受。 

四、测试结果

JavaScript 解析Json字符串的性能比较分析代码

注释:

*数值越小越好 

*在当前列中绿色背景的表示性能最好,红色性能最差 

1、Firefox2、3全部垫底,IE6的性能优于IE7(可能和机器不一致有关),Chrome和Safari4的性能远远超出其它浏览器。 

2、不同的浏览器下eval和new Function的性能不一致,总的来说eval更好,但Firefox下new Function的性能是eval的一倍,为了更好的兼容各个浏览器,我们把对JSON的解析单独封装成一个对象来处理: 

wrapper 

代码如下:

var __json = null;
if (typeof JSON !== "undefined") {
    __json = JSON;
}
var browser = Browser;
var JSON = {
    parse: function(text) {
        if (__json !== null) {
            return __json.parse(text);
        }
        if (browser.gecko) {
            return new Function("return " + text)();
        }
        return eval("(" + text + ")")
    }
};
var beginTime = new Date();
for (i = 0; i < count; i++) {
    o = JSON.parse(jsonString);
}
Console.output("wrapper:" + (new Date() - beginTime));

加入Wrapper后的结果: 

JavaScript 解析Json字符串的性能比较分析代码

由于涉及到调用对象的开销,封装后JSON对象会比单独调用更慢,但它能保证在各个浏览器下使用最适合的方法。 

五、结论 

解析Json字符串时,不同的浏览器选择不同的方法: 

  • IE6、7使用eval 
  • IE8使用原生的JSON对象 
  • Firefox2、3使用new Function 
  • Safari4使用eval 
  • 其它浏览器下eval和new Function的性能基本一致 

Update: 

2009.03.23:屏蔽所有Firefox的Add-Ons再进行测试 

由于Known在Firefox下运行代码得到了完全不一致的结果,怀疑是Firefox的插件导致,于是禁掉所有插件后(后来表明几乎由Firebug导致),重新在Firefox2、3下测试了一下,结果如下: 

JavaScript 解析Json字符串的性能比较分析代码

这表明Firefox本身的性能并不是象我们先前测试的那样低,在去掉插件后性能还是很不错。但是没有Firebug一类的插件支持,Firefox对我们的吸引力也大大降低了。 

2009.03.31:循环中每次使用新的json字符串 

根据Oliver的描述,他猜测是由于Safari4和Chrome缓存了eval的结果从而导致它们的测试成绩“虚”高,测试结果证明了他的推测: 

JavaScript 解析Json字符串的性能比较分析代码

从这个结果中我们可以看到,Opera的性能最好,Ie8其次。 

主要修改的代码: 

代码如下:

//eval 2: var beginTime = new Date(); 
for (i = 0; i < count; i++) {
    o = eval("(" + '{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}' + ")");
}
Console.output("eval:" + (new Date() - beginTime));
//new Function 
beginTime = new Date();
for (i = 0; i < count; i++) {
    o = new Function("return " + '{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}')();
}
Console.output("new Function:" + (new Date() - beginTime));
//native 
if (typeof JSON !== "undefined") {
    beginTime = new Date();
    for (i = 0; i < count; i++) {
        o = JSON.parse('{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}');
    }
    Console.output("native:" + (new Date() - beginTime));
} else {
    Console.output("native:not support!");
}
//wrapper 
var __json = null;
if (typeof JSON !== "undefined") {
    __json = JSON;
}
var browser = Browser;
var JSON = {
    parse: function(text) {
        if (__json !== null) {
            return __json.parse(text);
        }
        if (browser.gecko) {
            return new Function("return " + text)();
        }
        return eval("(" + text + ")")
    }
};
beginTime = new Date();
for (i = 0; i < count; i++) {
    o = JSON.parse('{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}');
}
Console.output("wrapper:" + (new Date() - beginTime));

附:全部代码

代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Parse JsonString</title> 
</head> 
<body> 
<div id="consoleRegion"></div> 
<script type="text/javascript"> 
//yui 
var Browser = function() { 
var o = { 
ie: 0, 
opera: 0, 
gecko: 0, 
webkit: 0 
}; 
var ua = navigator.userAgent, m; 
if ( ( /KHTML/ ).test( ua ) ) { 
o.webkit = 1; 
} 
// Modern WebKit browsers are at least X-Grade 
m = ua.match(/AppleWebKit\/([^\s]*)/); 
if (m&&m[1]) { 
o.webkit=parseFloat(m[1]); 
} 
if (!o.webkit) { // not webkit 
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) 
m=ua.match(/Opera[\s\/]([^\s]*)/); 
if (m&&m[1]) { 
o.opera=parseFloat(m[1]); 
} else { // not opera or webkit 
m=ua.match(/MSIE\s([^;]*)/); 
if (m&&m[1]) { 
o.ie=parseFloat(m[1]); 
} else { // not opera, webkit, or ie 
m=ua.match(/Gecko\/([^\s]*)/); 
if (m) { 
o.gecko=1; // Gecko detected, look for revision 
m=ua.match(/rv:([^\s\)]*)/); 
if (m&&m[1]) { 
o.gecko=parseFloat(m[1]); 
} 
} 
} 
} 
} 
return o; 
}(); 
var Console = { 
consoleRegion: null, 
getRegion: function() { 
if ( this.consoleRegion === null ) { 
this.consoleRegion = document.getElementById( "consoleRegion" ); 
} 
return this.consoleRegion; 
}, 
output: function( text ) { 
this.getRegion().innerHTML += "<br/>" + text; 
} 
}; 
//test code 
var count = 10000, o = null, i = 0, jsonString = '{"value":{"items": [{"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}'; 
//eval 
var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = eval( "(" + jsonString + ")" ); 
} 
Console.output( "eval:" + ( new Date() - beginTime ) ); 
//new Function 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = new Function( "return " + jsonString )(); 
} 
Console.output( "new Function:" + ( new Date() - beginTime ) ); 
//native 
if ( typeof JSON !== "undefined" ) { 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); 
} 
Console.output( "native:" + ( new Date() - beginTime ) ); 
} else { 
Console.output( "native:not support!" ); 
} 
//wrapper 
var __json = null; 
if ( typeof JSON !== "undefined" ) { 
__json = JSON; 
} 
var browser = Browser; 
var JSON = { 
parse: function( text ) { 
if ( __json !== null ) { 
return __json.parse( text ); 
} 
if ( browser.gecko ) { 
return new Function( "return " + text )(); 
} 
return eval( "(" + text + ")" ) 
} 
}; 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); 
} 
Console.output( "wrapper:" + ( new Date() - beginTime ) ); 
//alert( o.value.items[0].z ); 
</script> 
</body> 
</html> 

JavaScript解析json字符串代码:

代码一  一个 Servlet

java view plain copy 在CODE上查看代码片派生到我的代码片

package com.ghj.servlet;  
  
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
import com.google.gson.Gson;  
  
public class JsonServlet extends HttpServlet {  
  
    private static final long serialVersionUID = -699926309344319475L;  
  
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        doPost(request, response);  
    }  
      
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  
        response.setContentType("text/json;charset=utf-8");  
        PrintWriter out = response.getWriter();  
        Map<String, List<String>> dataMap = new HashMap<String, List<String>>();  
        List<String > gradeList = new ArrayList<String>();//年级  
        gradeList.add("初中一年级");  
        gradeList.add("初中二年级");  
        gradeList.add("初中三年级");  
        dataMap.put("gradeList", gradeList);  
          
        List<String> courseList = new ArrayList<String>();//课程  
        courseList.add("语文");  
        courseList.add("数学");  
        courseList.add("物理");  
        dataMap.put("courseList", courseList);  
        out.write(new Gson().toJson(dataMap));  
        out.flush();  
        out.close();  
    }  
}  

说明:这里使用了gson-2.2.2.jar包

代码二  一个jsp

html view plain copy 在CODE上查看代码片派生到我的代码片

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
<%  
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";  
%>  
  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
    <head>  
        <title>首页</title>  
        <script type="text/javascript" src="<%=basePath%>js/jquery-1.7.2.js"></script>  
        <script type="text/javascript">  
            $(function(){  
                $("#json").click(function(){  
                    $.ajax({  
                        type: "POST",  
                        url: "<%=basePath%>JsonServlet",  
                        success: function(data){  
                            var grades = data.gradeList;  
                            for(var index in grades){//年级  
                                console.log(grades[index]);  
                            }  
                            var courses = data.courseList;  
                            for(var index in courses){//课程  
                                console.log(courses[index]);  
                            }  
                        },  
                        error:function(){  
                            alert("数据请求失败!");  
                        }  
                    });  
                });  
            });  
        </script>  
    </head>  
  
    <body>  
        <button id="json">JavaScript解析JSON字符串</button>  
    </body>  
</html>  

JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等),易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。从Web API和服务端编程语言到NoSQL数据库和客户端框架,都有JSON的身影,在不同平台间传递数据方面,JSON已成为XML强有力的替代者。

主页 http://www.json.org/json-zh.htmljson
源码 https://github.com/topics/json

JSON目录

1. JSON教程
2.JSON 教程
3.JSON 基础
4.json格式
5.JSON 示例
6.JSON解析
7.JSON遍历
8.JSON调用
9.JSON转换
10.JSON获取
11.JSON字符串
12.JSON数组
13.JavaScript 教程
14.JSON 教程
15.JavaScript 注释
16.JavaScript 语句
17.JavaScript 输出
18.JavaScript 用法
19.JavaScript 简介
20.JavaScript switch 语句
21.JavaScript If…Else 语句
22.JavaScript 比较和逻辑运算符
23.JavaScript 运算符
24.JavaScript 函数
25.JavaScript 对象
26.JavaScript 数据类型
27.JavaScript 变量
28.JavaScript for 循环
29.JavaScript HTML DOM 事件
30.JavaScript HTML DOM 改变 CSS
31.JavaScript HTML DOM 改变 HTML 内容
32.JavaScript HTML DOM
33.JavaScript 表单验证
34.JavaScript 错误 – Throw、Try 和 Catch
35.JavaScript break 和 continue 语句
36.JavaScript while 循环
37.JavaScript HTML DOM 元素 (节点)
38.JavaScript Number 对象
39.JavaScript 对象
40.JavaScript Date(日期)对象
41.JavaScript 字符串(String)对象
42.JavaScript Window History
43.JavaScript Window Location
44.JavaScript Window Screen
45.JavaScript Window
46.JavaScript RegExp 对象
47.JavaScript Math(算数)对象
48.JavaScript Boolean(布尔)对象
49.JavaScript Array(数组)对象
50.JavaScript 实例
51.JavaScript 测试 Prototype
52.JavaScript 测试 jQuery
53.JavaScript 库
54.JavaScript Cookie
55.JavaScript 计时事件
56.JavaScript 弹窗
57.JavaScript Window Navigator
58.JavaScript HTML DOM 实例
59.JavaScript 对象实例
60.JavaScript 总结
61.JavaScript 浏览器对象实例
62.JSON 语法
63.JSON 使用
64.JSON 简介
65.JavaScript 保留关键字
66.JavaScript 字符串
67.JavaScript 事件
68.JavaScript 作用域
69.JavaScript JSON
70.JavaScript HTML DOM EventListener
71.JSONP 教程
72.javascript:void(0) 含义
73.JavaScript 语法
74.JavaScript 调试
75.JavaScript 闭包
76.JavaScript 函数调用
77.JavaScript 函数参数
78.JavaScript 函数定义
79.JavaScript 类型转换
80.JavaScript typeof, null, 和 undefined
81.JavaScript 正则表达式
82.JavaScript JSON.stringify()
83.JavaScript JSON.parse()
84.JavaScript 代码规范
85.JavaScript 使用误区
86.JavaScript 严格模式(use strict)
87.JavaScript 变量提升
88.JavaScript 验证 API
89.JavaScript 表单
90.JSON.stringify()
91.JSON.parse()
92.JSON 数组
93.JSON 对象
94.JavaScript HTML DOM 节点列表
95.JavaScript HTML DOM 集合(Collection)
96.JavaScript let 和 const
97.JavaScript this 关键字
98.JavaScript prototype(原型对象)
99.JSON vs XML
100.JavaScript Promise