在 Ruby 中解析 JSON 字符串
Posted
技术标签:
【中文标题】在 Ruby 中解析 JSON 字符串【英文标题】:Parsing a JSON string in Ruby 【发布时间】:2011-07-21 14:34:46 【问题描述】:我有一个要在 Ruby 中解析的字符串:
string = '"desc":"someKey":"someValue","anotherKey":"value","main_item":"stats":"a":8,"b":12,"c":10'
有没有简单的方法来提取数据?
【问题讨论】:
Ruby 直接支持 JSON,至少从 Ruby v1.9.3 开始就支持 JSON,因此除非您使用的是旧版本,否则无需安装 gem。只需在您的代码中使用require 'json'
。
【参考方案1】:
它看起来像一个 JSON 字符串。您可以使用许多 JSON 库之一,而且很简单:
JSON.parse(string)
【讨论】:
【参考方案2】:这看起来像javascript Object Notation (JSON)。您可以解析驻留在某个变量中的 JSON,例如json_string
,像这样:
require 'json'
JSON.parse(json_string)
如果您使用的是旧版 Ruby,则可能需要安装 json gem。
还有其他适用于 Ruby 的 JSON 实现可能更适合某些用例:
YAJL C Bindings for Ruby JSON::Stream【讨论】:
您还可以将选项 symbolize_names 设置为 true,以便将键作为符号。示例:JSON.parse(string, symbolize_names: true) #=> key: :value
Ruby 直接支持 JSON,至少从 Ruby v1.9.3 开始就支持 JSON,因此除非您使用的是旧版本,否则无需安装 gem。只需在您的代码中使用require 'json'
。【参考方案3】:
只是为了扩展一下如何处理已解析对象的答案:
# 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' "
不是。
@LinusAn 因为 JSON 需要在字符串两边加上双引号。请参阅 JSON 定义中的字符串 (json.org):“字符串是零个或多个 Unicode 字符的序列,用双引号括起来,使用反斜杠转义。”
在许多情况下,您希望将JSON.parse
包装在JSON::ParserError
的救援块中。
JSON.parse("[#value]")[0]
避免错误A JSON text must at least contain two octets!
【参考方案4】:
我建议使用 Oj,因为它比标准 JSON 库快 waaaaaay。
https://github.com/ohler55/oj
(see performance comparisons here)
【讨论】:
【参考方案5】:这有点晚了,但我遇到了一些有趣的东西,似乎很重要。
我不小心写了这段代码,它似乎可以工作:
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 版本数据的最简单方法。
【讨论】:
是的,JSON 实际上是由 Psych 代码解析的,它也在 Ruby 中解析 YAML。并且在Ruby v1.9.3中引入了JSON解析。 这行得通的原因是语义上(大多数)JSON 是有效的 YAML(尤其是 YAML 1.2)【参考方案6】:从 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。
【讨论】:
【参考方案7】:在这里看不到任何提到直接解析为哈希以外的对象的答案,但可以使用文档记录不佳的 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 选项。
【讨论】:
【参考方案8】:如果您想反序列化为您自己的类而不是 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
(参见类似的参数 @ 987654328@ 用于 JSON 数组的类似操作)。对于嵌套结构,这意味着您将使用同一个类来表示所有层:
> JSON.parse('"a":1, "b": "a": 32 ', object_class: MyClass)
=> #<MyClass:0x00007fb5110b2b38 @a=1, @b=#<MyClass:0x00007fb5110b2908 @a=32>>
【讨论】:
以上是关于在 Ruby 中解析 JSON 字符串的主要内容,如果未能解决你的问题,请参考以下文章
何时在 Ruby 的 JSON 库中使用转储与生成与 to_json 以及加载与解析?
如何转义json字符串中的单引号? JSON::ParserError Ruby