Android Volley JsonObjectRequest如何处理PHP返回的字符串响应?
解决Volley JsonObjectRequest接收字符串响应触发onErrorResponse的问题
这个问题我之前也碰到过——Volley的JsonObjectRequest会严格校验响应是否为合法JSON,哪怕后端返回200状态码,但响应是纯字符串(比如"OK"),它也会因为解析失败触发onErrorResponse,而不是进入预期的onResponse。下面给你两种可行的解决方案:
方案一:临时快速处理(在错误回调中提取字符串)
既然你已经在onErrorResponse里捕获到了200状态码的情况,直接在这里处理响应字符串就可以快速解决问题:
@Override public void onErrorResponse(VolleyError error) { Log.e("error", "error--->" + error.toString()); NetworkResponse response = error.networkResponse; Log.e("statusCode","statusCode--->"+response.statusCode); String json = null; if (response != null && response.data != null) { switch (response.statusCode) { // 保留其他状态码的处理逻辑 case 400: break; case 401: json = new String(response.data); break; case 502: json = new String(response.data); break; case 200: json = new String(response.data); // 这里直接处理字符串响应,比如判断是否是"OK" if ("OK".trim().equals(json)) { // 执行原本onResponse里的成功逻辑,比如提示用户操作完成 Toast.makeText(context, "操作成功", Toast.LENGTH_SHORT).show(); } progress.dismiss(); break; } } }
这种方法不用改动太多现有代码,适合快速收尾,但缺点是成功逻辑分散在错误回调中,代码结构不够优雅。
方案二:自定义Request(优雅长期解决方案)
更规范的做法是自定义一个支持字符串响应的Request,替代JsonObjectRequest,这样就能正常进入onResponse处理字符串,同时还能兼容后端后续可能返回JSON的情况:
1. 编写CustomStringRequest类
import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.toolbox.HttpHeaderParser; import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; public class CustomStringRequest extends Request<String> { private final Response.Listener<String> mListener; private byte[] mRequestBody; public CustomStringRequest(int method, String url, JSONObject jsonRequest, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; // 处理POST请求的JSON请求体 if (jsonRequest != null) { try { mRequestBody = jsonRequest.toString().getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsedResponse; try { parsedResponse = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { // 编码失败时直接用默认编码解析 parsedResponse = new String(response.data); } return Response.success(parsedResponse, HttpHeaderParser.parseCacheHeaders(response)); } @Override protected void deliverResponse(String response) { mListener.onResponse(response); } @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); return headers; } @Override public byte[] getBody() { return mRequestBody; } }
2. 使用CustomStringRequest替代JsonObjectRequest
修改你的ResponseTask方法:
private void ResponseTask() { if (queue == null) { queue = Volley.newRequestQueue(context); } CustomStringRequest req = new CustomStringRequest(Request.Method.POST, "", main, new Response.Listener<String>() { @Override public void onResponse(String response) { progress.dismiss(); Log.e("response","response--->"+response); // 这里可以灵活处理:如果后端有时返回JSON,有时返回字符串 try { // 尝试解析成JSON JSONObject jsonResponse = new JSONObject(response); // 处理JSON格式的响应逻辑 } catch (JSONException e) { // 解析失败,说明是纯字符串,比如"OK" if ("OK".trim().equals(response)) { // 处理字符串成功逻辑 } } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("error", "error--->" + error.toString()); progress.dismiss(); } }); req.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, 1f)); queue.add(req); }
问题根源解释
Volley的JsonObjectRequest继承自Request<JSONObject>,它的parseNetworkResponse方法会强制把响应体解析为JSONObject。如果后端返回的不是合法JSON(比如纯字符串"OK"),就会抛出ParseError,直接触发onErrorResponse,哪怕HTTP状态码是200。
内容的提问来源于stack exchange,提问作者karthik
相关产品推荐
相关产品推荐

