首先讓我們弄清楚出了什麼問題。這是你的代碼的近似修剪爲簡潔:
ids = ["d_sample_id1","d_sample_id2"]
puts %(curl ... -d '{"registration_ids": "#{ids}"}')
這裏我使用的puts %()
代替%x(...)
只打印字符串,而不是執行它。以下是輸出:
curl ... -d '{"registration_ids": "["d_sample_id1", "d_sample_id2"]"}'
發現問題?它在這裏:"["d_...
。你已經把你的數組放在雙引號內。當JSON解析器看到第一個雙引號時,它認爲「啊,這是一個字符串的開始」。然後到達下一個雙引號,在方括號後面,並且認爲,「這裏是字符串的結尾。」但接下來的字符是字母d
,在字符串之後沒有任何意義,所以解析器拋出一個錯誤並將其稱爲一天。
你可能通過刪除多餘的引號來解決這個問題。但最好是這樣做,因爲這個原因:它只能在附帶。在Ruby中使用字符串插值時,Ruby在#{...}
內的表達式上調用to_s
。但是,這只是偶然的,當你在一串Ruby字符串上調用to_s
時,你會得到有效的JSON。如果表達式是哈希或日期怎麼辦?字符串插值會使你失敗。
但即使你知道你剛剛得到了一個字符串數組,第二個原因也會導致插值失敗:你正在構建需要正確轉義的命令行參數。以此爲例:
arr = ["I can't even"]
%(curl ... -d '#{arr}')
發現問題?這將嘗試執行以下操作:
curl ... -d '["I can't even"]'
發現問題?這次你的單引號不匹配。
真是個噩夢!
這讓我們的拇指兩個重要的規則:
不要建立與字符串連接/插值JSON除非你喜歡痛苦和折磨。
使用字符串連接/插值來構建命令行參數時要非常小心,除非您享受痛苦和痛苦。
好在我們不必擔心我們的JSON被正確格式化或我們的命令行參數進行正確轉義,因爲許多聰明的人比我們已經擔心這些事情,把解決右轉入紅寶石的標準庫,在令人愉快的JSON和Shellwords模塊中。所以:
require "json"
require "shellwords"
ids = [ "d_sample_id1", "d_sample_id2" ]
data = {
registration_ids: ids,
collapse_key: "Turn",
data: {
title: "test",
sound: true,
body: "test",
badge: "1" ,
content_available: 1,
url: ""
}
}
json_arg = Shellwords.escape(data.to_json)
%x(curl \
--header 'Authorization: key=keynotmentioned' \
--header 'Content-Type: application/json' \
"https://android.googleapis.com/gcm/send" \
-d #{json_arg}
)
作爲獎勵,能夠建立我們的數據作爲一個Ruby的Hash使得它的方式更具可讀性,可維護性和可測試。
我剛剛嘗試過您的命令,完全如上所示,它對我來說工作得很好。你確定這是產生錯誤的線嗎? –