2016-07-08 32 views
0

次のJSONをRuby経由でCSVに変換しようとしていますが、コードに問題があります。私は私が行くように学習しているので、どんな助けもありがとう。JSONからCSVファイルへRuby

require 'json' 
require 'net/http' 
require 'uri' 
require 'csv' 

uri = 'https://www.mapquestapi.com/search/v2/radius?key=Imjtd%7Clu6t200zn0,bw=o5-layg1&radius=3000&callback=processPOIs&maxMatches=4000&origin=40.7686973%2C-73.9918181&hostedData=mqap.33882_stores_prod%7Copen_status%20=%20?%20OR%20open_status%20=%20?%20OR%20open_status%20=%20?%7CExisting,Coming%20Soon,New%7C' 

response = Net::HTTP.get_response(URI.parse(uri)) 

struct = JSON.parse(response.body.scan(/processPOIs\((.*)\);/).first.first) 


CSV.open("output.csv", "w") do |csv| 
    JSON.parse(struct).read.each do |hash| 
    csv << hash.values 
    end 
end 

私が受け取るエラーは、次のとおりです。

from c:/RailsInstaller/Ruby2.2.0/lib/ruby/gems/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `new' 
from c:/RailsInstaller/Ruby2.2.0/lib/ruby/gems/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `parse' 
from test.rb:14:in `block in <main>' 
from c:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1273:in `open' 
from test.rb:13:in `<main>' 

私は次のリンクをオフにすべてのデータを取得し、私は後で分析できるCSVファイルにそれを置くしようとしています。 https://www.mapquestapi.com/search/v2/radius?key=Imjtd%7Clu6t200zn0,bw=o5-layg1&radius=3000&callback=processPOIs&maxMatches=4000&origin=40.7686973%2C-73.9918181&hostedData=mqap.33882_stores_prod%7Copen_status%20=%20?%20OR%20open_status%20=%20?%20OR%20open_status%20=%20?%7CExisting,Coming%20Soon,New%7C

+0

あなたはどのような問題がありますか? –

+0

ちょうどCSVに書き込んでいません。 JSON.parse(構造体)の行を指すエラーが発生しています。 – awald

+0

どのようなエラーが表示されますか? 'response.body'はあなたが期待していると確信していますか? 'response.body.scan(/ processPOIs \((*。\); /)'が実際にJSONであることを確認しましたか? –

答えて

2

ここにはいくつかの問題がありますが、そのうちの最も重要なものはJSON.parseです。 2回目にstructに電話をかけると、初めてと呼んだ結果でした。基本的にはJSON.parse(JSON.parse(string))です。おっとっと。

もう一度JSON.parseと呼ぶ回線に別の問題があります。返信する値にreadを呼び出します。私が知る限り、JSON.parseは通常readに応答するものを返しません。これら2つのエラーを修正

は、あなたのコードは次のようなものになります。

struct = JSON.parse(response.body.scan(/processPOIs\((.*)\);/).first.first) 

CSV.open("output.csv", "w") do |csv| 
    struct.each do |hash| 
    csv << hash.values 
    end 
end 

をこれがstruct IIFを働くべきeachに応答オブジェクト(配列など)eachすべてで得られた値でありますvalues(ハッシュのような)に応答します。つまり、このコードでは、JSON.parseがハッシュの配列などを返すと仮定しています。それがうまくいかない場合、それはこの質問の範囲を超えています。余談として

、これは素晴らしいではありません。

response.body.scan(/processPOIs\((.*)\);/).first.first 

String#scanの目的は、正規表現に一致する文字列内のすべての部分文字列を見つけることです。しかし、あなたは最初の試合だけに関心があるので、scanは間違った選択です。

代替はString#matchを使用することです:

matches = response.body.match(/processPOIs\((.*)\)/) 
json = matches[1] 
struct = JSON.parse(json) 

しかし、それはやり過ぎだ。これはJSONPレスポンスなので、次のようになります:

processPOIs(...); 

...末尾にセミコロンまたは改行を付ける、または取ります。括弧内の部分を見つけるために正規表現は必要ありません。開始位置(インデックス12)から始まり13文字、終了位置の前に2文字( "index" -3)で終了します。 。つまり、String#[]別称、String#sliceとの容易な仕事、作る:

json = response.body[12..-3] 
struct = JSON.parse(json) 

私が言ったように、あなたは終了インデックスは、どのようなAPIが返すに依存することを微調整する必要があるかもしれませんので「与えるか、または末尾のセミコロンまたは改行を取ります」。それでは、これ以上の醜い.first.first、そしてそれも高速です。

0

ご協力いただきありがとうございます。私はCSVにすべてを手に入れることができましたし、それから私が望むようにVBAを使って整理しました。

require 'json' 
require 'net/http' 
require 'uri' 
require 'csv' 

uri = 'https://www.mapquestapi.com/search/v2/radius?key=Imjtd%7Clu6t200zn0,bw=o5-layg1&radius=3000&callback=processPOIs&maxMatches=4000&origin=40.7686973%2C-73.9918181&hostedData=mqap.33882_stores_prod%7Copen_status%20=%20?%20OR%20open_status%20=%20?%20OR%20open_status%20=%20?%7CExisting,Coming%20Soon,New%7C' 

response = Net::HTTP.get_response(URI.parse(uri)) 

matches = response.body.match(/processPOIs\((.*)\)/) 
json = response.body[12..-3] 
struct = JSON.parse(json) 

CSV.open("output.csv", "w") do |csv| 

    csv << struct['searchResults'].map { |result| result['fields']} 
    end 
関連する問題