You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用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

火山引擎 最新活动