什么是JavaScript中最快的JSON解析器?

3
我想使用Struts2支持的Json插件展示一个包含1000行的列表。我使用flexigrid (jquery)来解析1000行进行显示,但速度非常慢,有时浏览器会崩溃(Firefox和IE)。
那么,什么是解析大约1000行最快的Javascript框架?

3
你能展示一下你当前的代码吗?如果我要猜测的话,问题可能不在于JSON解析器的速度,而在于更新DOM的方式。 - Matt
你是否必须使用JSON?像CSV这样的简单格式比JSON更快解析。 - Gumbo
2
@Gumbo:解析真正的CSV是一件非常麻烦的事情;它不仅仅是data.split(",")这样简单。而JSON则非常容易(随着浏览器对显式解析JSON的支持改进,速度和符合性也在提高,因为人们已经意识到仅仅使用eval是一个坏主意)。此外,我怀疑数据解析并不是真正的问题所在。 - T.J. Crowder
@T.J. Crowder:但在JSON中,也有不同的数据类型可以嵌套。在CSV中,只有两种类型:带引号和不带引号的值。如果您的数据不需要引号,您可以使用类似于 data.split(",") 的东西。 - Gumbo
@Gumbo:确实如此。正如我所说,真正的 CSV 是很麻烦的。CSV-lite(即没有逗号作为分隔符等)确实很简单。但再次强调,我怀疑数据解析是否是问题的关键。 - T.J. Crowder
显示剩余2条评论
5个回答

16
什么是JavaScript中最快的JSON解析器?
在Chrome、Safari、Firefox 3.x、Opera 10.50甚至IE8(只有在IE8模式下)中,采用eval或原生JSON解析器可以实现更快的解析。

6

我通过Oracle存储过程获取了一个列表,但是它是不可更改的,因此无法使用可滚动的ResultSet与Oracle。(限制) - m0z4rt
2
无论如何,仍然要将数据缓存到某个地方,可以是在应用程序层或其他地方,然后从那里进行分页。当然,如果没有办法将数据留在某个临时的Oracle表(或类似的东西)中,我仍会感到惊讶 - 但这并不改变您可以将其缓存在其他地方的事实。 - cgp
请给我更多有关使用Spring JDBC和Oracle进行缓存的信息,谢谢 :) - m0z4rt

2
我认为,几乎任何一种显示1,000个项目的网格组件都无法提供可接受的性能,特别是在IE上(即使是IE8)。但是大多数网格应该能够支持将1,000个项目存储在内存中(这取决于它们的大小),并显示一个窗口(例如20行、40行等)进行分页和过滤,而不会出现显著的性能问题。我认为这将是更好的用户体验。

编辑

我很好奇去检查了一下,JSON解析时间不是问题;渲染才是问题。以下是一个非常简单(非生产环境)的完全客户端分页示例。在我的上网本上,IE7在36毫秒内解析了1,000行简单的JSON对象,因此即使是复杂对象也不应该成为问题。这是使用PrototypeevalJSON实现的,它(即使现在)只是将其推迟到eval并将数据放在括号中(他们将更改这一点)。

1000rows.html

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>1,000 Row Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
#log p {
    margin:     0;
    padding:    0;
}
</style>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js'></script>
<script type='text/javascript' src='1000rows.js'></script>
</head>
<body><div>
<input type='button' id='btnLoadData' value='Load Data'>
<input type='button' id='btnNext' value='Next'>
<input type='button' id='btnPrevious' value='Previous'>
<table>
<thead>
<tr><th>Name</th><th>Description</th><th>Count</th></tr>
</thead>
<tfoot>
<tr><th colspan='3' id='theLabel'></th></tr>
</tfoot>
<tbody id='theData'>
<tr><td colspan='3'></td></tr>
</tbody>
</table>
<hr>
<div id='log'></div>
</div></body>
</html>

1000rows.js(使用Prototype;jQuery会有所不同但相似)
(function() {
    var data, windowTop, WINDOW_SIZE;

    // "Constant" for the size of our window into the data
    WINDOW_SIZE = 20;   // Rows

    // No data yet
    clearData();

    // Hook up our observers when we can
    document.observe('dom:loaded', function() {
        $('btnLoadData').observe('click', loadData);
        $('btnNext').observe('click', function(event) {
            event.stop();
            updateWindow(WINDOW_SIZE);
        });
        $('btnPrevious').observe('click', function(event) {
            event.stop();
            updateWindow(-WINDOW_SIZE);
        });
    });

    // Clear our data to a known state
    function clearData() {
        data = [];
        windowTop = 0;
    }

    // Click handler for the load data button
    function loadData() {
        var success;

        log("Loading data..");
        clearData();
        updateWindow();
        success = false;

        // Note: Using text/plain rather than application/json so
        // Prototype doesn't parse the data for me, so I can measure
        // how long it takes to do it.
        new Ajax.Request("data.txt", {
            onSuccess: function(response) {
                var start, duration;

                success = true;
                log("Got data, parsing");
                start = new Date().getTime();
                data = response.responseText.evalJSON();
                duration = new Date().getTime() - start;
                log("Data parsed in " + duration + "ms");
                updateWindow.defer();
            }
        });
    }

    function updateWindow(offset) {
        var dataElement, labelElement, markup, index, template;

        // Get the target element
        dataElement = $('theData');
        labelElement = $('theLabel');
        if (!dataElement || !labelElement) {
            return;
        }

        // If no data, simply say that
        if (!data || data.length <= 0) {
            dataElement.update("");
            labelElement.update("No information");
            return;
        }

        // Ensure that windowTop is rational
        if (WINDOW_SIZE > data.length) {
            windowTop = 0;
        }
        else {
            if (typeof offset == 'number') {
                windowTop += offset;
            }
            if (windowTop + WINDOW_SIZE > data.length) {
                windowTop = data.length - WINDOW_SIZE;
            }
            if (windowTop < 0) {
                windowTop = 0;
            }
        }

        template = new Template(
            "<tr><td>#{name}</td><td>#{description}</td><td>#{count}</td></tr>"
        );

        markup = "";
        index = windowTop + WINDOW_SIZE - 1;
        if (index >= data.length) {
            index = data.length - 1;
        }
        $('theLabel').update('Showing rows ' + windowTop + ' through ' + index);
        while (index >= windowTop) {
            markup = template.evaluate(data[index]) + markup;
            --index;
        }

        dataElement.update(markup);
    }

    // Log a message
    function log(msg) {
        $('log').appendChild(new Element('p').update(msg));
    }
})();

数据.txt(当然很无聊)
[
    {"name": "Name #0001", "description": "Description #0001", "count": 1},
    {"name": "Name #0002", "description": "Description #0002", "count": 2},
    {"name": "Name #0003", "description": "Description #0003", "count": 3},
    ...
    {"name": "Name #1000", "description": "Description #1000", "count": 1000}
]

"...完整的data.txt副本可以在这里找到。"

W.0.W,你的代码太棒了。它真的很有帮助,谢谢你。 :) - m0z4rt

1

1,000行的什么?jQuery实际上相当快,特别是自从版本1.4(仅在几天前发布)进行了性能升级以来。如果您遇到显示1,000行的问题,我首先会问您为什么要显示那么多-没有人应该滚动那么多。其次,所有信息是否都至关重要,并且您只将关键信息传递到JSON值中。最后,您是否通过添加数据的方式使DOM变得不必要地复杂?

同样,如果您只查询需要显示的内容,并且显示合理数量的数据(在屏幕上发布1,000行不合理),那么jQuery将足以满足您的需求。


请检查我上面的回答评论,我使用Flexigrid加载了1000行,我认为问题的原因可能是Flexigrid :),我将更新更多关于jquery的内容,谢谢。 :) - m0z4rt

1
如果你真的想要速度,那么javascript中的eval("...");函数是最快的。不幸的是,它不安全,因为它可以执行恶意javascript代码。
此外,还有来自JSON.org的javascript JSON解析器(在这里找到)。他们编写了javascript来解析JSON字符串以创建JSON对象(我听说使用Firefox附加组件Firebug进行调试会创建一个JSON对象数组,但我从未尝试过)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接