使用AsyncTask发送POST请求时无法将JSON对象转为原始JSON字符串
问题诊断与解决方案
你的问题根源在于错误地将JSON对象转换成了表单格式的字符串,而不是直接发送标准的JSON格式内容。虽然你在请求头里设置了Content-Type: application/json,但实际发送的是key=value&key=value这种application/x-www-form-urlencoded格式的字符串,服务器自然无法识别为完整的JSON对象。
问题核心:getPostDataString方法完全不符合需求
这个方法的逻辑是把JSON对象的键值对拼接成表单提交格式,和JSON字符串的结构完全不匹配。比如你的嵌套JSON对象(比如product数组、addresses对象),用这个方法转换后会变成类似product=[Ljava.lang.Object;@xxxx这种无效的字符串,根本不是服务器期望的JSON结构。
正确的解决方案
直接使用JSONObject自带的toString()方法来生成标准的JSON字符串,然后写入输出流即可,完全不需要自己手动拼接。
步骤1:替换写入流的代码
把doInBackground里的这段代码:
writer.write(getPostDataString(postDataParams));
替换成:
writer.write(postDataParams.toString());
步骤2:删除无用的getPostDataString方法
这个方法是为表单提交设计的,在这里完全用不上,可以直接删除。
额外的逻辑修复提醒
你的代码里有一段重复覆盖addresses的错误:
// 先设置了包含billing的addresses JSONObject postDataAdd = new JSONObject(); postDataAdd.put("billing",postDataAddressBilling); postDataParams.put("addresses",postDataAdd); // 后面又重新设置了只包含shipping的addresses,覆盖了之前的billing JSONObject postDataShip = new JSONObject(); postDataShip.put("shipping",postDataAddressShipping); postDataParams.put("addresses",postDataShip);
这会导致服务器最终只能收到shipping地址,billing地址会丢失。正确的做法是把两个地址放在同一个addresses对象里:
JSONObject postDataAddresses = new JSONObject(); postDataAddresses.put("billing", postDataAddressBilling); postDataAddresses.put("shipping", postDataAddressShipping); postDataParams.put("addresses", postDataAddresses);
修改后的核心代码片段
// ... 构建postDataParams的逻辑 ... // 正确合并账单地址和送货地址 JSONObject postDataAddresses = new JSONObject(); postDataAddresses.put("billing", postDataAddressBilling); postDataAddresses.put("shipping", postDataAddressShipping); postDataParams.put("addresses", postDataAddresses); postDataParams.put("coupon", orderReq.coupon); postDataParams.put("customerId", orderReq.customerId); postDataParams.put("newCustomerAddress", orderReq.newCustomerAddress); postDataParams.put("paymentMethod", null); postDataParams.put("shippingMethod", "firstfreeship_firstfreeship"); JSONObject postDataPayment = new JSONObject(); postDataPayment.put("method", null); postDataParams.put("payment", postDataPayment); // 建立连接并发送请求 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(15000 /* milliseconds */); conn.setConnectTimeout(15000 /* milliseconds */); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); conn.setDoInput(true); conn.setDoOutput(true); OutputStream os = conn.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); // 直接使用toString()生成标准JSON字符串 writer.write(postDataParams.toString()); writer.flush(); writer.close(); os.close(); // ... 后续响应处理逻辑 ...
这样修改后,你发送的就是服务器期望的完整JSON格式字符串,就能正常解析了。
内容的提问来源于stack exchange,提问作者pankaj




