我有一个字符串,想在Ruby中解析它:
string = '{"desc":{"someKey":"someValue","anotherKey":"value"},"main_item":{"stats":{"a":8,"b":12,"c":10}}}'
有没有简单的方法提取数据?
这看起来像是JavaScript对象表示法(JSON)。你可以解析储存在某个变量中的 JSON,例如json_string
:
require 'json'
JSON.parse(json_string)
如果您正在使用较旧的 Ruby 版本,则可能需要安装 json gem。
还有其他适用于 Ruby 的 JSON 实现,可能更适合某些用例:
JSON.parse(string, symbolize_names: true) #=> {key: :value}
- Nando Sousarequire 'json'
即可。 - the Tin Man仅仅扩展一下对已解析对象的处理方法:
# 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
'{ "a": "bob" }'
是有效的。"{ 'a': 'bob' }"
不是有效的。 - ZiggyJSON.parse
包装在JSON::ParserError
的救援块中。 - johnmlJSON.parse("[#{value}]")[0]
转换用于避免 A JSON text must at least contain two octets!
错误。 - Rivenfall从 Ruby v1.9.3 开始,您无需安装任何 Gem 就可以解析 JSON,只需使用 require 'json'
:
require 'json'
json = JSON.parse '{"foo":"bar", "ping":"pong"}'
puts json['foo'] # prints "bar"
请在 Ruby-Doc 中查看 JSON。
看起来是一个JSON字符串。你可以使用许多JSON库,它就像这样简单:
JSON.parse(string)
这里没有提到将解析直接转换成除哈希外的其他对象的答案,但是可以使用文档不太完整的 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
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版本的情况下,这是提取数据的最简单方法。
如果你想将反序列化应用到自己的类,而不是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
(请参阅类似操作array_class
参数以处理JSON数组)。对于嵌套结构,这意味着您将使用相同的类来表示所有层级。> JSON.parse('{"a":1, "b":{ "a": 32 }}', object_class: MyClass)
=> #<MyClass:0x00007fb5110b2b38 @a=1, @b=#<MyClass:0x00007fb5110b2908 @a=32>>
require 'json'
即可。 - the Tin Man