在 Ruby 中解析 JSON 字符串
我有一个想要在 Ruby 中解析的字符串:
string = '{"desc":{"someKey":"someValue","anotherKey":"value"},"main_item":{"stats":{"a":8,"b":12,"c":10}}}'
有没有一种简单的方法来提取数据?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这看起来像 JavaScript 对象表示法 (JSON)。您可以解析驻留在某个变量中的 JSON,例如
json_string
,如下所示:如果您使用的是较旧的 Ruby,则可能需要安装 json gem。
还有其他用于 Ruby 的 JSON 实现可能更适合某些用例:
This looks like JavaScript Object Notation (JSON). You can parse JSON that resides in some variable, e.g.
json_string
, like so:If you’re using an older Ruby, you may need to install the json gem.
There are also other implementations of JSON for Ruby that may fit some use-cases better:
只是为了稍微扩展一下如何处理解析对象的答案:
Just to extend the answers a bit with what to do with the parsed object:
从 Ruby v1.9.3 开始,您不需要安装任何 Gems 来解析 JSON,只需使用
require 'json'
:请参阅 JSON 位于 Ruby-Doc。
As of Ruby v1.9.3 you don't need to install any Gems in order to parse JSON, simply use
require 'json'
:See JSON at Ruby-Doc.
它看起来像一个 JSON 字符串。您可以使用众多 JSON 库之一,就像执行以下操作一样简单:
It looks like a JSON string. You can use one of many JSON libraries and it's as simple as doing:
这里没有看到任何提到直接解析为哈希以外的对象的答案,但可以使用记录不充分的 object_class 选项(请参阅 https://ruby-doc.org/stdlib-2.7.1/libdoc/json/rdoc/JSON.html):
阅读该选项的更好方法是“JSON 对象变成的 ruby 类”,这解释了为什么它默认为 Hash。同样,json 数组有一个 array_class 选项。
Don't see any answers here that mention parsing directly to an object other than a Hash, but it is possible using the poorly-documented object_class option(see https://ruby-doc.org/stdlib-2.7.1/libdoc/json/rdoc/JSON.html):
The better way to read that option is "The ruby class that a json object turns into", which explains why it defaults to Hash. Likewise, there is an array_class option for json arrays.
虽然有点晚了,但我遇到了一些有趣的事情,似乎对我的贡献很重要。
我不小心写了这段代码,它似乎有效:
我很惊讶地看到它有效,因为我使用的是 YAML 库,但它有效。
它之所以重要,是因为
yaml
内置于 Ruby,因此无需安装 gem。我使用的是 1.8.x 和 1.9.x 版本 - 因此
json
库不是内置的,但它位于 2.x 版本中。所以从技术上来说——这是提取低于 2.0 版本的数据的最简单方法。
This is a bit late but I ran into something interesting that seems important to contribute.
I accidentally wrote this code, and it seems to work:
I was surprised to see it works since I am using the YAML library, but it works.
The reason why it is important is that
yaml
comes built-in with Ruby so there's no gem install.I am using versions 1.8.x and 1.9.x - so the
json
library is not built in, but it is in version 2.x.So technically - this is the easiest way to extract the data in version lower than 2.0.
我建议使用 Oj,因为它比标准 JSON 库快得多。
https://github.com/ohler55/oj
(在此处查看性能比较)
I suggest Oj as it is waaaaaay faster than the standard JSON library.
https://github.com/ohler55/oj
(see performance comparisons here)
如果您想反序列化为您自己的类而不是 OpenStruct,则不需要做很多工作即可实现以下目的:
您所要做的就是提供一个零参数构造函数并实现
#[]=
方法。如果你不想暴露它,让它成为私有的就足够了:JSON.parse
将调用的在 irb 中尝试一下:
这种方法的一个警告是它只适用于平面结构,因为
object_class
参数确实告诉解析器应该使用什么类来反序列化字符串中的 JSON 对象,而不是Hash
(请参阅类似的参数array_class
以了解 JSON 数组的类似操作)。对于嵌套结构,这意味着您将使用相同的类来表示所有层:If you want to deserialise to your own class instead of OpenStruct it doesn't take a lot of work to make the following possible:
All you have to do is to provide a zero-argument constructor and implement the
#[]=
method whichJSON.parse
will call. If you don't want to expose it, it's sufficient to let it be private:Trying it out in irb:
A caveat with this approach is that it only works for flat structures, because the
object_class
argument really tells the parser what class it should use to deserialise JSON objects in the string instead ofHash
(see the similar argumentarray_class
for the analogous operation for JSON arrays). For nested structures this will mean you will use the same class to represent all layers: