我如何解析JSON与Ruby on Rails?

我正在寻找一种简单的方法来解析JSON,提取值并将其写入Rails中的数据库。

具体来说,我正在寻找的是从位返回的JSON中提取shortUrl的方法。ly API:

{
"errorCode": 0,
"errorMessage": "",
"results":
{
"http://www.foo.com":
{
"hash": "e5TEd",
"shortKeywordUrl": "",
"shortUrl": "http://bit.ly/1a0p8G",
"userHash": "1a0p8G"
}
},
"statusCode": "OK"
}

然后把那个短URL写进一个与长URL相关的ActiveRecord对象。

这是我可以完全从概念上思考的事情之一,当我坐下来执行时,我意识到我有很多东西要学习。

329056 次浏览

在Rails中解析JSON非常简单:

parsed_json = ActiveSupport::JSON.decode(your_json_string)

让我们假设,您希望将shortUrl与之关联的对象是一个Site对象,该对象具有两个属性——short_url和long_url。然后,要获得shortUrl并将其与适当的Site对象相关联,您可以这样做:

parsed_json["results"].each do |longUrl, convertedUrl|
site = Site.find_by_long_url(longUrl)
site.short_url = convertedUrl["shortUrl"]
site.save
end

这个答案相当古老。Pguardiario拿到了。

要查看的一个站点是Ruby的JSON实现。这个网站提供了一个gem,你可以安装一个更快的C扩展变体。

对于给定的文档页面基准,他们声称它比ActiveSupport::JSON.decode21.500倍

代码将与Milan Novota的回答相同,但解析将只是:

parsed_json = JSON(your_json_string)

这些答案有点过时了。因此,我给你:

hash = JSON.parse string

Rails应该自动为你加载json模块,所以你需要添加require 'json'

你可以尝试这样做:

def details_to_json
{
:id                    => self.id,
:credit_period_type    => self.credit_period_type,
:credit_payment_period => self.credit_payment_period,


}.to_json
end

RUBY区分大小写。

require 'json' # json must be lower case


JSON.parse(<json object>)

例如

JSON.parse(response.body) # JSON must be all upper-case

以下是2013年的最新情况。

Ruby

Ruby 1.9有一个默认的带有C扩展的JSON的宝石。你可以用它

require 'json'
JSON.parse ''{ "x": "y" }'
# => {"x"=>"y"}

parse!变体可用于安全源。还有其他宝石,它们可能比默认实现更快。列表请参考multi_json

Rails

现代版本的Rails使用multi_json,这是一个自动使用最快的JSON gem的gem。因此,推荐的方法是使用

object = ActiveSupport::JSON.decode json_string

更多信息请参考ActiveSupport这样::JSON。特别地,方法源中的重要行是

data = MultiJson.load(json, options)

然后在您的Gemfile中,包含您想要使用的宝石。例如,

group :production do
gem 'oj'
end
require 'json'
out=JSON.parse(input)

这将返回一个哈希

Ruby的绑定JSON能够自己展示一点魔力。

如果你有一个包含JSON序列化数据的字符串,你想要解析:

JSON[string_to_parse]

JSON会查看参数,看到它是一个字符串,并尝试解码它。

类似地,如果你有一个想要序列化的哈希或数组,使用:

JSON[array_of_values]

或者:

JSON[hash_of_values]

JSON会序列化它。如果你想避免[]方法的视觉相似性,你也可以使用to_json方法。

下面是一些例子:

hash_of_values = {'foo' => 1, 'bar' => 2}
array_of_values = [hash_of_values]


JSON[hash_of_values]
# => "{\"foo\":1,\"bar\":2}"


JSON[array_of_values]
# => "[{\"foo\":1,\"bar\":2}]"


string_to_parse = array_of_values.to_json
JSON[string_to_parse]
# => [{"foo"=>1, "bar"=>2}]

如果你在JSON中查找,你可能会注意到它是YAML的一个子集,实际上YAML解析器是处理JSON的。你也可以这样做:

require 'yaml'


YAML.load(string_to_parse)
# => [{"foo"=>1, "bar"=>2}]

如果你的应用程序同时解析YAML和JSON,你可以让YAML处理这两种类型的序列化数据。

Oj宝石(https://github.com/ohler55/oj)应该工作。它简单快捷。

http://www.ohler.com/oj/#Simple_JSON_Writing_and_Parsing_Example

require 'oj'


h = { 'one' => 1, 'array' => [ true, false ] }
json = Oj.dump(h)


# json =
# {
#   "one":1,
#   "array":[
#     true,
#     false
#   ]
# }


h2 = Oj.load(json)
puts "Same? #{h == h2}"
# true

Oj宝石对JRuby不起作用。对于JRuby, this (https://github.com/ralfstx/minimal-json)或this (https://github.com/clojure/data.json)可能是不错的选择。

require 'json'


hash = JSON.parse string

使用散列,做你想做的事情。

我会这么做:

json = "{\"errorCode\":0,\"errorMessage\":\"\",\"results\":{\"http://www.foo.com\":{\"hash\":\"e5TEd\",\"shortKeywordUrl\":\"\",\"shortUrl\":\"http://b.i.t.ly/1a0p8G\",\"userHash\":\"1a0p8G\"}},\"statusCode\":\"OK\"}"


hash = JSON.parse(json)
results = hash[:results]

如果你知道源url,那么你可以使用:

source_url = "http://www.foo.com".to_sym


results.fetch(source_url)[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

如果你不知道源url的键,你可以这样做:

results.fetch(results.keys[0])[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

如果你不想使用符号查找键,你可以将散列中的键转换为字符串:

results = json[:results].stringify_keys


results.fetch(results.keys[0])["shortUrl"]
=> "http://b.i.t.ly/1a0p8G"

如果您担心JSON结构可能会发生变化,您可以构建一个简单的JSON Schema,并在尝试访问密钥之前验证JSON。这将提供一个保护。

注意:钻头必须破损。因为发布规则,Ly url。

这可以如下所示,只需要使用JSON.parse,然后你可以用索引正常遍历它。

#ideally not really needed, but in case if JSON.parse is not identifiable in your module
require 'json'


#Assuming data from bitly api is stored in json_data here


json_data = '{
"errorCode": 0,
"errorMessage": "",
"results":
{
"http://www.foo.com":
{
"hash": "e5TEd",
"shortKeywordUrl": "",
"shortUrl": "http://whateverurl",
"userHash": "1a0p8G"
}
},
"statusCode": "OK"
}'


final_data = JSON.parse(json_data)
puts final_data["results"]["http://www.foo.com"]["shortUrl"]