您好我通过%x()在ruby应用程序中的curl命令中传递了一组id,但是我无法将这些抛出错误添加为:
JSON_PARSING_ERROR: Unexpected character (d) at position
数组:@m = ["d_sample_id1","d_sample_id2"]
使用的命令:
%x(curl --header 'Authorization: key=keynotmentioned' --header 'Content-Type: application/json' https://android.googleapis.com/gcm/send -d '{"registration_ids": "#{@m}", "collapse_key": "Turn", "data": { "title": "test", "sound": true,"body": "test", "badge": "1" , "content_available": 1 ,"url": ""}}')
显示json解析错误,你可以帮我解决这个问题吗? 提前完成。
答案 0 :(得分:2)
首先让我们弄清楚出了什么问题。这是为了简洁而修剪代码的近似值:
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,这只是偶然的。如果表达式是Hash或Date,该怎么办?字符串插值会让你失望。
但即使你知道你刚刚得到一个字符串数组,插值也会因为第二个原因而失败:你需要构建命令行参数,这需要正确转义。以此为例:
arr = ["I can't even"]
%(curl ... -d '#{arr}')
发现问题?这将尝试执行以下操作:
curl ... -d '["I can't even"]'
发现问题?这次你的单引号不匹配。
多么噩梦!
这引出了两个重要的经验法则:
除非您喜欢痛苦和痛苦,否则不要使用字符串连接/插值构建JSON。
使用字符串连接/插值来构建命令行参数时要非常小心,除非您喜欢痛苦和痛苦。
幸运的是,我们不必担心我们的JSON格式正确或我们的命令行参数被正确转义,因为比我们更聪明的人已经担心这些事情并将解决方案直接放入Ruby&#39标准库,令人愉快的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使其更具可读性,可维护性和可测试性。