6

我在http://hndroidapi.appspot.com/news/format/json/page/?appid=test从远程 json 提取数据。我遇到的问题是这个 API 似乎在构建 JSON 时没有正确处理 UTF-8 编码(如果我在这里错了,请纠正我)。例如,现在通过的部分结果是

{
"title":"IPad - please don€™t ding while you and I are asleep  ",
"url":"http://modern-products.tumblr.com/post/25384729998/ipad-please-dont-ding-while-you-and-i-are-asleep",
"score":"10 points",
"user":"roee",
"comments":"18 comments",
"time":"1 hour ago",
"item_id":"4128497",
"description":"10 points by roee 1 hour ago  | 18 comments"
}

注意don€™t. 这不是它令人窒息的唯一类型的角色。鉴于我不控制 API,我能做些什么来将数据转换为干净的东西吗?

编辑:

这是我拉下 JSON 的方式:

hn_url = "http://hndroidapi.appspot.com/news/format/json/page/?appid=test"
  url = URI.parse(hn_url)

  # Attempt to get the json
  req = Net::HTTP::Get.new(hn_url)
  req.add_field('User-Agent', 'Test')
  res = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }
  response = res.body
  if response.nil?
    puts "Bad response when fetching HN json"
    return
  end

  # Attempt to parse the json
  result = JSON.parse(response)
  if result.nil?
    puts "Error parsing HN json"
    return
  end

编辑2:

刚刚找到 API 的 GitHub 页面。看起来这是一个悬而未决的问题。仍然不确定我是否可以从最后做任何解决方法: https ://github.com/glebpopov/Hacker-News-Droid-API/issues/4

4

2 回答 2

4

看起来您收到的 JSON 响应正文是以 US-ASCII 而不是 UTF-8 接收的,因为Net::HTTP故意不强制编码。

1.9.3p194 :044 > puts res.body.encoding
US-ASCII

在 Ruby 1.9.3 中,如果您知道编码应该是什么,您可以强制编码。尝试这个:

response = res.body.force_encoding('UTF-8')

JSON 解析器应该按照您希望的方式处理 UTF-8。

参考

于 2012-06-18T23:00:08.283 回答
2

使用force_encoding似乎是最好的解决方案。跟进凯文迪克森的回答,这里是对怪异的解释。

Net::HTTP有点乱。

在 1.9.3 上

  • 如果服务器发送分块响应,您总是会得到 ASCII-8BIT。这似乎优先于其他情况。
  • 如果你http.request用一个Get对象调用,你会得到 US-ASCII。此方法不会为您进行压缩。
  • 如果您调用http.get,则启用压缩。
    • 如果服务器支持压缩,你会得到 ASCII-8BIT
    • 如果服务器不发送压缩体,你会得到 US-ASCII

你会得到 US-ASCII,因为当Net::HTTP创建缓冲区字符串来接收响应时,它是在解释器的默认源文件编码中创建的,即 US-ASCII。(net/源文件,顶部没有魔术编码注释,所以它们使用 ruby​​ 的默认值。)

解压缩会产生 ASCII-8BIT,因为它get在解压缩时在方法中进行了硬编码。

在 2.0上,您似乎总是得到 UTF-8,但这是因为这是默认的源文件编码。如果您通过-K选项更改它,响应编码将相应更改。尝试将n, e, s,传递u-K.

于 2014-05-22T18:35:16.157 回答