URL-адрес JSON из API StackExchange, возвращающий тарабарщину?

У меня есть ощущение, что я делаю что-то не так, но я не совсем уверен, что я пропустил шаг, или у меня просто проблема с кодировкой или что-то в этом роде. Вот мой код:

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);
   }

Когда я печатаю контент, я получаю целую кучу крыльев и специальных символов, в основном тарабарщины. Я бы скопировал и вставил сюда, но это не работает. Что я делаю не так?


person shsteimer    schedule 22.05.2010    source источник


Ответы (3)


В данном случае проблема не в кодировке символов, а в кодировке контента; вы ожидаете текст, но сервер использует сжатие для экономии полосы пропускания. Если вы посмотрите на заголовки при захвате этого URL-адреса, вы увидите, что сервер, к которому вы подключаетесь, возвращает сжатый контент:

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
<more headers>
Content-Encoding: gzip
<more headers>

Таким образом, вам либо нужно использовать более умный клиент, такой как Apache HttpClient, как предлагает stevedbrown (хотя вам нужно настройка, чтобы заставить его автоматически говорить Gzip), или явно распаковать поток, который вы получили в своем примере кода . Попробуйте это вместо строки, в которой вы объявляете свой ввод:

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

Я проверил, что это работает для URL-адреса, который вы пытаетесь получить.

person Bkkbrad    schedule 22.05.2010

Вместо этого используйте HTTP-клиент Apache, он позаботится о правильном преобразовании символов. Из примеры этого сайта:

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<String> 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.

person stevedbrown    schedule 22.05.2010
comment
Это не решает проблему распаковки содержимого, которое возвращает api.stackoverflow.com. - person Bkkbrad; 22.05.2010

Иногда ответ на вызов API сжимается, например. API-интерфейс StackExchange. Пожалуйста, просмотрите их документацию и проверьте, какое сжатие они используют. Некоторые используют сжатие GZIP или DEFLATE. В случае сжатия GZIP используйте следующее.

InputStream is = new URL(url).openStream();
BufferedReader in = new BufferedReader(new InputStreamReader(new GZIPInputStream(is)));
person Trideep Rath    schedule 23.09.2014