【问题标题】:What is the fastest JSON parser for JavaScript?JavaScript 最快的 JSON 解析器是什么?
【发布时间】:2010-01-18 13:49:33
【问题描述】:

我想使用 Struts2 支持的 Json 显示一个包含 1000 行的列表,例如 pug-in。我使用 flexigrid (jquery) 来解析 1000 行来显示。但它太慢了,有时我的浏览器会崩溃。 (火狐和 IE)。

那么,解析大约 1000 行的最快的 Javascript 框架是什么?

【问题讨论】:

  • 你能显示你当前的代码吗?如果我不得不猜测,那么慢的不是 JSON 解析器,而是您使用所述数据更新 DOM 的方式。
  • 您需要使用 JSON 吗?像 CSV 这样的普通格式比 JSON 解析要快得多。
  • @Gumbo: True CSV 解析起来很麻烦;这不仅仅是data.split(",") 的问题。而 JSON 是一件轻而易举的事(随着浏览器改进对显式解析 JSON 的支持,速度和一致性也在提高,因为人们已经发现只使用 eval 它是一个坏主意)。此外,我怀疑数据解析是真正的问题。
  • @T.J. Crowder:但是在 JSON 中也有不同的数据类型可以嵌套。在 CSV 中,您只有两个:带引号的值和不带引号的值。如果您的数据不需要引用,您可以使用 data.split(",") 之类的内容。
  • @Gumbo:确实如此。正如我所说,true CSV 很痛苦。 CSV-lite,如果你愿意的话(除了分隔符等没有逗号)确实很容易。但同样,我怀疑数据解析是问题所在。

标签: javascript jquery json flexigrid


【解决方案1】:

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

eval 或可用的原生 JSON 解析器,至少在 Chrome、Safari、Firefox 3.something、Opera 10.50 甚至 IE8 中(仅在 IE8 模式下)

【讨论】:

    【解决方案2】:

    向用户展示他们想看到的内容。

    显示 50 行,添加过滤器或搜索。

    如果你真的认为数据应该可以在一个页面中访问,也许你想要的是fetch data while the user scrolls (and thus pick up smaller portions at a time).

    【讨论】:

    • 我得到一个由 Oracle 过程返回的列表,因此它不能更改,因此不能将可滚动的 ResultSet 与 Oracle 一起使用。(限制)
    • 仍然,将数据缓存在某个地方,无论是在应用层还是其他地方,然后从那里分页。当然,如果没有办法将数据留在某个临时 Oracle 表(或类似的东西)中,我仍然会感到惊讶——但这不会改变您可以将其缓存在其他地方的事实。
    • 请给我更多关于使用 spring jdbc 和 oracle 进行缓存的信息,谢谢 :)
    【解决方案3】:

    我认为您不会从几乎任何同时显示 1,000 个的网格组件中获得可接受的性能,尤其是在 IE(甚至 IE8)上。但是大多数网格应该能够支持在内存中有 1,000 个(嗯,取决于它们有多大)并在其中显示一个带有分页和过滤选项的窗口(例如,20 行、40 行等),而没有显着的性能问题。我想这也会是更好的用户体验。

    编辑

    我好奇地检查了一下,是的,JSON 解析时间不是问题;这将是渲染。下面是一个非常非常简单(非生产)的完全客户端分页的示例。在我的上网本上,IE7 在 36 毫秒内解析了 1000 行简单的 JSON 对象,因此即使是复杂的对象也不应该成为问题。那是使用 Prototype's evalJSON,它(即使是现在)只是遵循 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));
        }
    })();
    

    data.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 的完整副本可以在here找到。

    【讨论】:

    • W.0.W,你的代码太棒了。真的很有帮助,谢谢你。 :)
    【解决方案4】:

    1,000 行什么? jQuery 实际上非常快,尤其是在 1.4 版(几天前发布)中进行了性能升级之后。如果您在显示 1,000 行时遇到问题,我首先会问您为什么要显示这么多行 - 没有人应该滚动那么多。其次,所有信息都至关重要,您是否仅将关键信息传递到 JSON 值中。最后,您添加数据的方式是否让您的 DOM 变得不必要地复杂化了?

    再一次,如果您只查询 需要 显示的内容,并且显示的数据合理(在屏幕上发布 1,000 行是' t 合理),jQuery 将足以满足您的需求。

    【讨论】:

    • 请检查我上面的答案评论,我使用 Flexigrid 加载 1000 行,我认为问题的原因是我的 Fexigrid :),我会更新更多关于 jquery 的信息,谢谢你。 :)
    【解决方案5】:

    如果你真的想要速度,javascript eval("..."); 函数是最快的。不幸的是,它不安全,因为它可以执行恶意 javascript。

    还有来自 JSON.org 的 javascript JSON Parser(找到 here)。他们编写了 javascript 来解析 JSON 字符串以创建 JSON 对象(我听说使用 Firebug 进行调试,一个 Firefox 插件会创建一个 JSON 对象数组,但我从未尝试过)。

    【讨论】:

      猜你喜欢
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 2017-09-21
      • 1970-01-01
      相关资源
      最近更新 更多