私はJSONを解析し、値を抽出してRailsのデータベースに書き込むための簡単な方法を探しています。
特に私が探しているのは、bit.ly APIから返されたJSONからshortUrl
を抽出する方法です。
{
"errorCode": 0,
"errorMessage": "",
"results":
{
"http://www.foo.com":
{
"hash": "e5TEd",
"shortKeywordUrl": "",
"shortUrl": "http://bit.ly/1a0p8G",
"userHash": "1a0p8G"
}
},
"statusCode": "OK"
}
そしてそのshortUrlを取得して、それを長いURLに関連付けられたActiveRecordオブジェクトに書き込みます。
これは私が完全に概念的に考えることができるそれらのうちの1つであり、私が実行するために座るとき私は私が学ぶべきことがたくさんあることに気づく。
これらの答えは少し古くなっています。だから私はあなたにあげる:
hash = JSON.parse string
Railsは自動的にjson
モジュールを自動的にロードしますので、require 'json'
を追加する必要はありません必要はありません。
RailsでJSONを解析するのはとても簡単です。
parsed_json = ActiveSupport::JSON.decode(your_json_string)
ShortUrlを関連付けるオブジェクトがSiteオブジェクトで、2つの属性(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はそれを持っています。
チェックアウトする1つのサイトは、 Ruby用のJSON実装です 。このサイトはあなたがはるかに速いC拡張の変種のためにインストールすることができる宝石を提供します。
彼らの ドキュメントページ に与えられたベンチマークで彼らはそれがActiveSupport::JSON.decode
よりも21.500x速いと主張します
コードは、この宝石に関するMilan Novotaの答えと同じですが、解析は以下のようになります。
parsed_json = JSON(your_json_string)
これは2013年の更新です。
Ruby 1.9にはデフォルトの JSON gem とC拡張があります。あなたはそれを使用することができます
require 'json'
JSON.parse ''{ "x": "y" }'
# => {"x"=>"y"}
parse!
バリアントは、安全なソースに使用できます。他のgemもあります。これはデフォルトの実装より速いかもしれません。リストについては multi_json を参照してください。
最新バージョンのRailsは multi_json を使用します。これは、利用可能な最も速いJSON gemを自動的に使用するgemです。したがって、推奨される方法は使用することです
object = ActiveSupport::JSON.decode json_string
詳しくは ActiveSupport :: JSON を参照してください。特に、メソッドソースの重要な行は
data = MultiJson.load(json, options)
それからあなたのGemfileに、あなたが使いたいgemを含めてください。例えば、
group :production do
gem 'oj'
end
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に両方の種類のシリアル化データを処理させることができます。
require 'json'
out=JSON.parse(input)
これはハッシュを返します
require 'json'
hash = JSON.parse string
ハッシュを操作して、やりたいことをします。
これは以下のように行うことができます。単に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"]
これが私のやり方です。
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スキーマを作成してキーにアクセスする前にJSONを検証することができます。これはガードを提供します。
注:投稿ルールのため、bit.lyのURLを変更する必要がありました。
Rubyは大文字と小文字を区別します。
require 'json' # json must be lower case
JSON.parse(<json object>)
例えば
JSON.parse(response.body) # JSON must be all upper-case
Oj gem( 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 gemはJRubyでは動きません。 JRubyの場合はこちら( https://github.com/ralfstx/minimal-json )またはこちら( https: //github.com/clojure/data.json )が良い選択肢かもしれません。