在Ruby中解析JSON字符串

我有一个字符串,我想在Ruby中解析:

string = '{"desc":{"someKey":"someValue","anotherKey":"value"},"main_item":{"stats":{"a":8,"b":12,"c":10}}}'

是否有一种简单的方法来提取数据?

528438 次浏览

它看起来像一个JSON字符串。你可以使用许多JSON库之一,它就像这样简单:

JSON.parse(string)

它看起来像JavaScript对象表示法。你可以像这样解析驻留在某个变量中的JSON,例如json_string:

require 'json'
JSON.parse(json_string)

如果你使用的是较旧的Ruby,你可能需要安装json的宝石


还有一些其他的Ruby JSON实现可能更适合一些用例:

只是扩展一下答案,关于如何处理解析对象:

# JSON Parsing example
require "rubygems" # don't need this if you're Ruby v1.9.3 or higher
require "json"


string = '{"desc":{"someKey":"someValue","anotherKey":"value"},"main_item":{"stats":{"a":8,"b":12,"c":10}}}'
parsed = JSON.parse(string) # returns a hash


p parsed["desc"]["someKey"]
p parsed["main_item"]["stats"]["a"]


# Read JSON from a file, iterate over objects
file = open("shops.json")
json = file.read


parsed = JSON.parse(json)


parsed["shop"].each do |shop|
p shop["id"]
end

我建议使用Oj,因为它比标准JSON库快得多。

https://github.com/ohler55/oj

(在这里查看性能比较)

这有点晚了,但我遇到了一些有趣的东西,似乎很重要。

我不小心写了这段代码,它似乎可以工作:

require 'yaml'
CONFIG_FILE = ENV['CONFIG_FILE'] # path to a JSON config file
configs = YAML.load_file("#{CONFIG_FILE}")
puts configs['desc']['someKey']

我很惊讶地看到它工作,因为我正在使用YAML库,但它工作。

它之所以重要是因为yaml是Ruby内置的,所以不需要安装gem。

我使用的是1.8版本。X和1.9。x -所以json库不是内置的,但它在版本2.x中。

所以从技术上讲,这是在低于2.0的版本中提取数据的最简单的方法。

从Ruby v1.9.3开始,你不需要安装任何Gems来解析JSON,只需使用require 'json':

require 'json'


json = JSON.parse '{"foo":"bar", "ping":"pong"}'
puts json['foo'] # prints "bar"

参见Ruby-Doc中的JSON

这里没有看到任何回答提到直接解析到哈希以外的对象,但可以使用文档不完善的object_class选项(参见https://ruby-doc.org/stdlib-2.7.1/libdoc/json/rdoc/JSON.html):

JSON.parse('{"foo":{"bar": 2}}', object_class: OpenStruct).foo.bar
=> 2

读取该选项的更好方法是&;json对象转换成的ruby类&;,这解释了为什么它默认为Hash。同样,json数组也有一个array_class选项。

如果你想反序列化到你自己的类,而不是OpenStruct,它不需要很多工作,使以下可能:

require 'json'
# result is an instance of MyClass
result = JSON.parse(some_json_string, object_class: MyClass)

你所要做的就是提供一个零参数的构造函数,并实现#[]=方法,JSON.parse将调用这个方法。如果你不想暴露它,让它私有就足够了:

class MyClass
attr_reader :a, :b


private


def []=(key, value)
case key
when 'a' then @a = value
when 'b' then @b = value
end
end
end

尝试在irb:

> JSON.parse('{"a":1, "b":2}', object_class: MyClass)
=> #<MyClass:0x00007fe00913ae98 @a=1, @b=2>

这种方法需要注意的是,它只适用于平面结构,因为object_class参数真正告诉解析器应该使用哪个类来反序列化字符串中的JSON对象,而不是Hash(关于JSON数组的类似操作,请参阅类似参数array_class)。对于嵌套结构,这意味着你将使用相同的类来表示所有层:

> JSON.parse('{"a":1, "b":{ "a": 32 }}', object_class: MyClass)
=> #<MyClass:0x00007fb5110b2b38 @a=1, @b=#<MyClass:0x00007fb5110b2908 @a=32>>