DOM 是解析 JSON 的唯一方法吗?
11 回答
一些 JSON 解析器确实提供增量(“流式”)解析器;对于 Java,至少以下来自 json.org 页面的解析器提供了这样的接口:
- Jackson(拉接口)
- Json-simple(SAX 风格的推送接口)
(除了另一个答案提到的 Software Monkey 的解析器)
实际上,这么多 JSON 解析器不提供这个简单的低级接口有点奇怪——毕竟,他们已经需要实现低级解析,所以为什么不公开它。
编辑(2011 年 6 月):Gson 也有自己的流 API(使用 gson 1.6)
通过 DOM,我假设您的意思是解析器会在您使用它之前一次读取整个文档。请注意,现在说 DOM 往往意味着 XML,但 IMO 这并不是一个准确的推论。
因此,在回答您的问题时——“是”,有流式 API 和“否”,DOM 不是唯一的方法。也就是说,将 JSON 文档作为流处理通常是有问题的,因为许多对象不是简单的字段/值对,而是包含其他对象作为值,您需要对其进行解析以进行处理,这往往会导致递归。但是对于简单的消息,您可以使用基于流/事件的解析器来做有用的事情。
我已经为 JSON 编写了一个 pull-event 解析器(它是一个类,大约 700 行)。但我见过的大多数其他人都是面向文档的。我在解析器之上构建的层之一是文档阅读器,它占用了大约 30 LOC。我只在实践中将我的解析器用作文档加载器(出于上述原因)。
我敢肯定,如果您搜索网络,您会发现基于拉取和推送的 JSON 解析器。
编辑:我已将解析器发布到我的网站以供下载。包括一个可工作的可编译类和一个完整的示例。
EDIT2:您还需要查看JSON 网站。
正如 stefanB 提到的,http ://lloyd.github.com/yajl/是一个用于流解析 JSON 的 C 库。该页面上还提到了许多其他语言的包装器:
- yajl-ruby - YAJL 的红宝石绑定
- yajl-objc - YAJL 的 Objective-C 绑定
- YAJL IO 绑定(用于 IO 语言)
- Python 绑定有两种风格,py-yajl 或 yajl-py
- yajl-js - node.js 绑定(镜像到 github)。
- lua-yajl - lua 绑定
- ooc-yajl - ooc 绑定
- yajl-tcl - tcl 绑定
其中一些可能不允许流式传输,但其中许多肯定允许。
免责声明:我建议我自己的项目。
我在 Javascript 中维护了一个流式 JSON 解析器,它结合了 SAX 和 DOM 的一些特性:
这个想法是允许流解析,但不需要程序员像使用原始 SAX 那样监听许多不同的事件。我喜欢 SAX,但对于大多数人的需求来说,它的级别往往很低。您可以通过注册 JSONPath 模式从 JSON 流中侦听任何有趣的节点。
代码在 Github 上:
如果你想使用纯 JavaScript 和一个在 node.js 和浏览器中运行的库,你可以尝试 clarinet:
https://github.com/dscape/clarinet
解析器是基于事件的,并且由于它是流式传输的,因此可以处理大文件。API 非常接近 sax,并且代码是从 sax-js 派生的。
LitJSON 支持流式 API。引用手册:
“一些开发人员可能熟悉的处理 JSON 数据的替代接口是通过类,这些类可以以类似流的方式读取和写入数据。这些类是JsonReader
和JsonWriter
.
“这两种类型实际上是这个库的基础,JsonMapper
类型是建立在它们之上的,所以在某种程度上,开发人员可以将 reader 和 writer 类视为 LitJSON 的低级编程接口。”
这是一个用于解析和处理 JSON 流的 NodeJS NPM 库: https ://npmjs.org/package/JSONStream
对于 Python,ijson 的替代方案(显然更轻且更高效)是jsaone(请参阅该链接以获取粗略的基准,显示 jsaone 大约快 3 倍)。
免责声明:我是 jsaone 的作者,我所做的测试非常基础......我很高兴被证明是错误的!
回答问题标题:YAJL a JSON parser library in C:
YAJL 会记住支持重新启动解析所需的所有状态。这允许在从磁盘或网络读取数据时逐步进行解析。
所以我猜想使用 yajl 来解析 JSON 可以被认为是处理数据流。
在回答您的第二个问题时,不,许多语言都有 JSON 解析器。PHP、Java、C、Ruby 等等。只是谷歌为您选择的语言加上“JSON 解析器”。