StackExchange API的JSON URL返回乱码?

我有一种感觉,我在这里做错了,但我不太确定我是否错过了一步,或者只是遇到了编码问题。 这是我的代码:

URL url = new URL("http://api.stackoverflow.com/0.8/questions/2886661"); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); // Question q = new Gson().fromJson(in, Question.class); String line; StringBuffer content = new StringBuffer(); while ((line = in.readLine()) != null) { content.append(line); } 

当我打印内容时,我会得到一大堆的翅膀和特殊的角色,基本上是乱七八糟的。 我会复制并通过它,但这不起作用。 我究竟做错了什么?

在这种情况下,它不是字符编码问题,它是内容编码问题; 你期待文本,但服务器正在使用压缩来节省带宽。 如果您在获取该URL时查看标题,则可以看到您要连接的服务器正在返回gzip压缩的内容:

 GET /0.8/questions/2886661 HTTP/1.1 Host: api.stackoverflow.com HTTP/1.1 200 OK Server: nginx Date: Sat, 22 May 2010 15:51:34 GMT Content-Type: application/json; charset=utf-8  Content-Encoding: gzip  

因此,您需要使用像Apache的HttpClient这样的智能客户端,因为stevedbrown建议(尽管您需要通过调整来让它自动说Gzip ),或者明确解压缩您在示例代码中获得的流。 请在您声明输入的行中尝试此操作:

  BufferedReader in = new BufferedReader(new InputStreamReader(new GZIPInputStream(url.openStream()))); 

我已经确认这适用于您要抓取的url。

使用Apache Http Client ,它将正确地处理字符转换。 从该网站的例子 :

 public final static void main(String[] args) throws Exception { HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://api.stackoverflow.com/0.8/questions/2886661"); System.out.println("executing request " + httpget.getURI()); // Create a response handler ResponseHandler responseHandler = new BasicResponseHandler(); String responseBody = httpclient.execute(httpget, responseHandler); System.out.println(responseBody); System.out.println("----------------------------------------"); // When HttpClient instance is no longer needed, // shut down the connection manager to ensure // immediate deallocation of all system resources httpclient.getConnectionManager().shutdown(); } 

在这种情况下,请参阅http://svn.apache.org/repos/asf/httpcomponents/httpclient/branches/4.0.x/httpclient/src/examples/org/apache/http/examples/client/ClientGZipContentCompression.java ,其中展示了如何处理Gzip内容。

有时API调用响应被压缩,例如。 StackExchange API。 请仔细阅读他们的文档并检查他们正在使用的压缩程序。 有些使用GZIP或DEFLATE压缩。在GZIP压缩的情况下使用以下内容。

 InputStream is = new URL(url).openStream(); BufferedReader in = new BufferedReader(new InputStreamReader(new GZIPInputStream(is)));