我正在使用HTTParty从Google检索此信息:http://www.google.com/ig/calculator?hl=en&q=1USD=?COP
data = HTTParty.get("http://www.google.com/ig/calculator?hl=en&q=1USD=?COP").body
=> "{lhs: \"1 U.S. dollar\",rhs: \"1\xA0901.14068 Colombian pesos\",error: \"\",icc: true}"
我想解析数据并使用JSON.parse(data)
将其显示为JSON对象,但它会返回错误:
JSON.parse(data)
JSON::ParserError: 746: unexpected token at '{lhs: "1 U.S. dollar",rhs: "1�901.14068 Colombian pesos",error: "",icc: true}'
from /usr/lib/ruby/1.9.1/json/common.rb:148:in `parse'
from /usr/lib/ruby/1.9.1/json/common.rb:148:in `parse'
from (irb):39
from /usr/bin/irb:12:in `<main>'
我想获取该信息并将其显示在我的网站上以供其使用,但我无法解析它。
答案 0 :(得分:2)
快速但危险:使用eval
代替JSON.parse
:
data = HTTParty.get("http://www.google.com/ig/calculator?hl=en&q=1USD=?COP").body
=> "{lhs: \"1 U.S. dollar\",rhs: \"1\xA0901.14068 Colombian pesos\",error: \"\",icc: true}"
eval(data)
=> {:lhs=>"1 U.S. dollar", :rhs=>"1\xA0901.14068 Colombian pesos", :error=>"", :icc=>true}
要获得更安全的解决方案,我们应该手动解析响应,或者学习如何从谷歌获取有效的JSON。
如您所见,您的响应正文不是有效的JSON。密钥未包含在"
。
以下是有关同一问题的Python相关讨论:How to Read a Simple Json Result (from Google calculator) in Python?
简而言之,解决方案要么手动解析回复,要么使用http://rate-exchange.appspot.com代替Google。
答案 1 :(得分:2)
我一直在四处寻找,我认为问题出在谷歌的最后。
接收的数据是Ruby中的哈希值,或JavaScript中的对象,根据规范,keys should be quoted because they're strings。对象包含在{
和}
中,格式为"string": value
。字符串用双引号括起来:"string"
。
通过预处理接收的数据以将键名转换为带引号的键名,可以解析JSON:
require 'open-uri'
require 'json'
FIELDS = %w[lhs rhs error icc]
%w[COP USD AED YER ZAR ZMK].each do |currency|
data = open('http://www.google.com/ig/calculator?hl=en&q=1USD=?' + currency).read
FIELDS.each { |f| data.sub!(f, %Q["#{f}"]) }
puts JSON[data]
end
运行后,这些是通过解析JSON创建的哈希:
{"lhs"=>"1 U.S. dollar", "rhs"=>"1 890.35917 Colombian pesos", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"1 U.S. dollar", "error"=>"0", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"3.67290571 United Arab Emirates dirhams", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"215.053763 Yemeni rials", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"9.97575891 South African rands", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"5 208.33333 Zambia kwacha", "error"=>"", "icc"=>true}
但等等,还有更多......
YAML是JSON的超集,因此YAML解析器应该能够理解JSON。将收到的“JSON”扔进YAML解析器会处理不带引号的键:
require 'open-uri'
require 'yaml'
%w[COP USD AED YER ZAR ZMK].each do |currency|
data = open('http://www.google.com/ig/calculator?hl=en&q=1USD=?' + currency).read
puts YAML.load(data)
end
使用此输出:
{"lhs"=>"1 U.S. dollar", "rhs"=>"1 890.35917 Colombian pesos", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"1 U.S. dollar", "error"=>"0", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"3.67290571 United Arab Emirates dirhams", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"215.053763 Yemeni rials", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"9.97575891 South African rands", "error"=>"", "icc"=>true}
{"lhs"=>"1 U.S. dollar", "rhs"=>"5 208.33333 Zambia kwacha", "error"=>"", "icc"=>true}
YAML并不坚持引用哈希键。对于那些显然不是数字的东西,它默认为String,这是我尝试YAML的线索。
所以,在我看来,谷歌做错了。如果他们要输出JSON,他们应该输出正常的,语法正确的JSON。如果他们要输出YAML,他们应该输出常规的YAML,而不是输出数据的“半快”序列化。 API可能有某种方式强制它,但它应该默认为解析的JSON。
您可能希望改为使用https://openexchangerates.org/。他们的示例输出似乎是一种更加理智的方法。