2016-07-08 27 views
0

我想通過Ruby將下面的JSON轉換爲CSV,但我的代碼有問題。我正在學習,所以任何幫助表示讚賞。JSON到CSV文件紅寶石

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(struct)行的錯誤。 – awald

+0

你有什麼錯誤?你確定'response.body'是你期望的嗎?你是否檢查過'response.body.scan(/ processPOIs \((。*)\); /)'實際上是JSON? –

回答

2

這裏有幾個問題,其中最重要的是你打電話JSON.parse兩次。你第二次打電話給struct,這是第一次致電JSON.parse的結果。你基本上在做JSON.parse(JSON.parse(string))。哎呀。

第二次撥打電話JSON.parse的線路上還存在另一個問題:您可以撥打read返回該值。據我所知JSON.parse通常不會返回任何迴應read

修復這兩個錯誤,你的代碼看起來是這樣的:

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 

這應該工作IIFstruct是響應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(...); 

...給出或採用尾隨分號或換行符。我們不需要一個正則表達式來查找括號內的部分,因爲我們已經知道它在哪裏:它從起始處開始13個字符(即索引12)並在結束之前結束兩個字符(「索引」-3) 。這使得它與String#slice容易的工作,又名String#[]

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