Android Kotlin使用Volley向Magento REST API发送JSON请求时遭遇JSON解析错误的技术问询
解决Volley请求Magento REST API时的ParseError问题
咱们先拆解你遇到的错误:com.android.volley.ParseError: org.json.JSONException: Value [] of type org.json.JSONArray cannot be converted to JSONObject,核心原因非常明确:你用了Volley的JsonObjectRequest发送请求,但Magento API返回的响应是JSON数组([]格式),而不是单个JSON对象({}格式),Volley强行按JSONObject去解析数组,自然就抛出了转换错误。
再看你的代码,请求体部分其实完全符合Magento文档要求(只是变量名itemsArray起得有点误导人,实际是JSONObject,不过不影响功能),问题出在响应解析的类型匹配上。下面给你两个可行的解决方案:
方案一:改用JsonArrayRequest适配响应格式
既然API返回的是JSON数组,直接把请求类型换成JsonArrayRequest即可,不过要注意JsonArrayRequest默认期望请求体也是JSON数组,所以需要重写getBody方法传入我们的JSONObject请求体:
// 保持请求体构建逻辑不变,把变量名改得更清晰 val itemsObject = JSONObject() itemsObject.put("sku", "10-1001") itemsObject.put("qty", 5) itemsObject.put("quote_id", "3") val requestBody = JSONObject() requestBody.put("cartItem", itemsObject) // 替换为JsonArrayRequest val jsonRequest = object : JsonArrayRequest( Request.Method.POST, url, null, // 这里传null,后续通过重写getBody传入请求体 Response.Listener { response -> try { // 现在可以正常处理JSONArray类型的响应 binding.txtStatus.text = response.toString() } catch (e: JSONException) { e.printStackTrace() binding.txtStatus.text = e.toString() } }, Response.ErrorListener { error -> binding.txtStatus.text = error.toString() }) { @Throws(AuthFailureError::class) override fun getBodyContentType(): String { return "application/json" } override fun getHeaders(): Map<String, String> { val apiHeader = HashMap<String, String>() apiHeader["Authorization"] = "Bearer $cusToken" return apiHeader } // 重写getBody方法,传入我们构建的JSONObject请求体 override fun getBody(): ByteArray { return requestBody.toString().toByteArray(Charsets.UTF_8) } } val queue = Volley.newRequestQueue(this@MainActivity) queue.add(jsonRequest)
方案二:用StringRequest手动解析响应(更灵活)
如果不确定API后续会不会返回不同格式的响应,或者想自己控制解析逻辑,用StringRequest先拿到原始响应字符串,再手动判断解析会更稳妥:
// 请求体构建逻辑不变 val itemsObject = JSONObject() itemsObject.put("sku", "10-1001") itemsObject.put("qty", 5) itemsObject.put("quote_id", "3") val requestBody = JSONObject() requestBody.put("cartItem", itemsObject) val jsonRequest = object : StringRequest( Request.Method.POST, url, Response.Listener { response -> try { // 手动判断响应是数组还是对象 if (response.trimStart().startsWith("[")) { val jsonArray = JSONArray(response) binding.txtStatus.text = "返回数组:$jsonArray" } else { val jsonObject = JSONObject(response) binding.txtStatus.text = "返回对象:$jsonObject" } } catch (e: JSONException) { e.printStackTrace() binding.txtStatus.text = "解析失败:${e.toString()}" } }, Response.ErrorListener { error -> binding.txtStatus.text = error.toString() }) { @Throws(AuthFailureError::class) override fun getBodyContentType(): String { return "application/json" } override fun getHeaders(): Map<String, String> { val apiHeader = HashMap<String, String>() apiHeader["Authorization"] = "Bearer $cusToken" return apiHeader } override fun getBody(): ByteArray { return requestBody.toString().toByteArray(Charsets.UTF_8) } } val queue = Volley.newRequestQueue(this@MainActivity) queue.add(jsonRequest)
最后小提醒:你可以先用Postman之类的工具测试这个API端点,确认响应格式,同时检查请求URL是否正确、token是否有效,这些基础问题也可能导致异常响应哦。
内容的提问来源于stack exchange,提问作者TEN_KUNG
相关产品推荐
相关产品推荐

