2014-10-15 5 views
0

Я создаю приложение для Android, которое втягивает и отображает данные из JSON api.Вытягивание данных JSON дает код ответа 200, но длина содержимого -1, которая разбивает все

В частности, JSON API, что я вытягивать из является here

URL blogFeedUrl = new URL("http://www.johncorser.com/?json=1&count=15/"); 
    HttpURLConnection connection = (HttpURLConnection)blogFeedUrl.openConnection(); 
    connection.connect(); 
    responseCode = connection.getResponseCode(); 
    Log.i(TAG, "Code: " + responseCode); 
    Log.i(TAG, "Length " + connection.getContentLength()); 
    if (responseCode == HttpURLConnection.HTTP_OK){ 
     InputStream inputStream = connection.getInputStream(); 
     Reader reader = new InputStreamReader(inputStream); 
     int contentLength = connection.getContentLength(); 
     char[] charArray = new char[contentLength]; //Line 97, where the error is thrown because contentLength == -1 
     reader.read(charArray); 
     String responseData = new String(charArray); 
     jsonResponse = new JSONObject(responseData); 

    } 
    else { 
     Log.i(TAG, "Unsuccessful HTTP response code: " + responseCode); 
    } 

Когда я запускаю это, LogCat дает мне эту StackTrace:

10-15 11:36:00.512 8704-8718/com.johncorser.johncorser I/MainListActivity﹕ Code: 200 
10-15 11:36:00.512 8704-8718/com.johncorser.johncorser I/MainListActivity﹕ Length -1 
10-15 11:36:00.512 8704-8718/com.johncorser.johncorser E/MainListActivity﹕ Exception caught: 
    java.lang.NegativeArraySizeException: -1 
      at com.johncorser.johncorser.MainListActivity$GetBlogPostTask.doInBackground(MainListActivity.java:97) 
      at com.johncorser.johncorser.MainListActivity$GetBlogPostTask.doInBackground(MainListActivity.java:80) 
      at android.os.AsyncTask$2.call(AsyncTask.java:288) 
      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
      at java.lang.Thread.run(Thread.java:841) 

Странной часть, если я поменять api с одним структурированным почти идентичным образом, как один here, код выполняется без ошибок.

Любая идея, почему я не могу загрузить эти конкретные данные JSON?

ответ

1

Дело в том, что данные возвращает сервис в кусках (Transfer-Encoding:chunked в заголовках ответа), поэтому он не знает содержания длины в то время, он отправляет заголовки.

Чтобы справиться с такой ситуацией, вы можете просто обернуть InputStreamReader в BufferedReader и читать построчно:

BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); 

StringBuilder responseBuilder = new StringBuilder(); 
String chunk; 
while ((chunk = br.readLine()) != null) { 
    responseBuilder.append(chunk); 
}    

String responseData = responseBuilder.toString(); 
+0

Это решается быстро и легко, и объяснил ошибку, которую я сделал в очень простым способом. – johncorser

1

Если длина содержимого неизвестна, когда сервер отправляет заголовки, то он не сообщает клиенту длину; это означает, что клиент не знает длину, а вызов возвращает -1. Подробности: in the Javadoc для URLConnection.

В практическом плане это означает, что вы не можете сделать это с помощью массива с фиксированной длиной. Вы должны прочитать ответ строки за строкой, в StringBuilder, пока вы не исчерпали вход. Затем вы можете поместить результат в свой конструктор JSONObject.

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

Вот заголовки ваш веб-сайт johncorser.com возвращается на этой странице:

HTTP/1.1 200 OK 
Date: Wed, 15 Oct 2014 15:40:15 GMT 
Server: Apache 
Set-Cookie: PHPSESSID=82ivean17opsfkqjf9n4itdog2; path=/ 
Expires: Thu, 19 Nov 1981 08:52:00 GMT 
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 
Pragma: no-cache 
X-Pingback: http://www.johncorser.com/xmlrpc.php 
Content-Type: application/json; charset=UTF-8 

Примечание нет ничего о длине там. Но teamtreehouse.com сайта вы также связаны с аналогичной структурой, возвращает это:

HTTP/1.1 200 OK 
Server: nginx 
Date: Wed, 15 Oct 2014 15:46:59 GMT 
Content-Type: application/json; charset=UTF-8 
Content-Length: 4422 
Connection: keep-alive 
Keep-Alive: timeout=20 
X-Pingback: http://blog.teamtreehouse.com/xmlrpc.php 
X-Cacheable: SHORT 
Vary: Accept-Encoding,Cookie 
Cache-Control: max-age=600, must-revalidate 
Accept-Ranges: bytes 
X-Cache: HIT: 2 
X-Cache-Group: normal 
X-Type: default 

Обратите внимание, что это один включает в себя Content-Length: 4422.

Смежные вопросы