JSON响应被截断,Android

5

我看到了很多关于这个话题的帖子,但是没有一个能解决我的问题。

问题在于从服务器返回的JSON响应被截断了,因此当我尝试将响应放入JSONArray中时,会出现JSONException。

    json = new JSONArray(EntityUtils.toString(response.getEntity()));

这里是整个代码:
    private class AsyncFetchForms extends AsyncTask<String, Void, JSONArray> {

    private HttpClient mClient = new DefaultHttpClient();
    private AsyncTaskCompleteListener<JSONArray> listener;
    private String serverUrl;
    private String credentials;

    private ProgressDialog progressDialog;
    private HttpGet httpGet;
    private String response;
    private BasicResponseHandler responseHandler;
    private boolean showDialog;
    private JSONArray json;



    public AsyncFetchForms(String url, String message, AsyncTaskCompleteListener<JSONArray> listener, boolean showDialog)
    {
        serverUrl = Utils.getServerUrl(context) + url;
        credentials = Utils.getUserCredentials(context);
        this.listener = listener;
        this.showDialog = showDialog;

        httpGet = new HttpGet(serverUrl);
        httpGet.setHeader("Authorization", "Basic " + credentials);
        httpGet.setHeader("Accept", "application/json");
        httpGet.setHeader("Accept-Encoding", "gzip");
        httpGet.setHeader("Connection", "keep-alive");

        responseHandler = new BasicResponseHandler();


        if(showDialog)
        {
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage(message);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);          
            progressDialog.show();
        }
    }


    @Override
    protected JSONArray doInBackground(String... params) {

        try {
            HttpResponse response = mClient.execute(httpGet);


            if (response.getStatusLine().getStatusCode() == 200) {

                json = new JSONArray(EntityUtils.toString(response.getEntity()));

                return json;
            }
        } catch (ClientProtocolException e) {
           e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(JSONArray result) {
        System.out.println(result.toString());

    }
}

有人能看出问题吗?

请问能提供一下URL吗?还有您收到的JSON数据是什么?(请使用pastebin上传JSON并提供链接) - apmartin1991
4个回答

5

Logcat 只能显示大约 4000 个字符。因此,您需要实现一个递归函数来查看整个日志。请使用以下函数来查看整个日志:

public static void longInfo(String str) {
    if (str.length() > 4000) {
        Log.d("", str.substring(0, 4000));
        longInfo(str.substring(4000));
    } else
        Log.d("", str);
}

2
这个不需要被实现为递归函数,也不应该是。一旦你有了足够长的字符串,你就会超出堆栈大小并进入堆栈溢出。此外,如果您需要打印超过4000个字符以调试代码,您可能应该重新考虑您的调试策略。 - Lie Ryan
@LieRyan 我指的是这一行:System.out.println(result.toString()); 迭代也可以实现,但我手头上有递归的代码。至于你提到的堆栈溢出,我不认为这段代码会引起它,因为我在我的项目中使用了这段代码来打印非常长的JSON。 - Illegal Argument
@IllegalArgumemt:在桌面Java虚拟机中,递归调用的数量限制通常为1000次,超过这个数字就会导致堆栈溢出。假设这个数字,您可以打印的最大字符串大小为4000 * 1000个字符,约为4 MB。只要您的字符串大小不超过此限制,就是安全的。然而,首先将那么多文本打印到logcat可能并不是一个好主意。 - Lie Ryan
非常感谢。我太高兴了,想哭了。这帮助我调试了我的问题。它给了我反馈,JSONObject无法解析为JSONArray,从那里修复错误就很容易了。再次感谢! - user3906863

1
如果您(或您的团队)自己实现服务器端,第一件事是检查服务器是否返回正确的HTTP响应。特别是,如果您通过HTTP传输数据,则需要有正确的Content-Length,否则您的数据将被截断。此外,Content-Length必须是在应用任何传输编码后的数据长度,换句话说,在数据被gzip压缩后的长度之后。或者,使用分块传输。
其次,请确保您的服务器生成有效的JSON。也许您错过了一个闭合括号之类的东西。也许您需要解析JSON对象而不是JSON数组。
此外,如果收到异常,请始终发布整个traceback。

0

首先,尝试记录EntityUtils.toString(response.getEntity())响应,并确保它以"["开头而不是"{",即它是一个jsonArray而不是jsonObject

然后尝试在浏览器中打开URL(如果可用),并确保没有编码问题。

最后,如果问题仍然存在,请将错误日志输出发送给我们。


谢谢。那正是我的问题,我试图将一个JSONObject解析成JSONArray。上面的被接受的答案帮助我输出了整个logcat堆栈跟踪。 - user3906863

0

这个回答完全跑题了,但是:

你在这里想做什么?你知道有一些库可以为你完成所有这些无聊的工作吗?

当我谈论无聊的工作时,我指的是管理所有后台运行的东西(比如AsyncTask)、JSON解码和HTTP响应。我知道有时候这很烦人(我也曾经历过),但现在我选择不再担心这些问题,而是使用一个专门的库:http://square.github.io/retrofit/

这个小宝贝将联系您选择的Web服务,下载JSON并将其放入自定义Java类中,其中包含您想要处理的所有属性。

如果您将其与ORMLite之类的东西连接起来,它甚至可以将您的JSON响应对象保存到SQLite数据库中,您可以以相同的方式访问它(通过设置所有属性来“填充”Java类对象)。

就我个人而言,我无法想象自己手动完成所有这些工作,这只会带来麻烦而没有好处=)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接