如何使用Retrofit 2向PHP发送对象?POST请求异常解决
解决Retrofit 2 POST请求的
Expected BEGIN_OBJECT but was STRING异常 问题根源
你的问题核心是请求格式不匹配:
- Java代码用
@Body Lost lost发送的是JSON格式的请求体 - 但PHP代码是通过
$_POST接收**表单编码(x-www-form-urlencoded)**的数据,而且PHP执行完后没有返回任何JSON结构的响应——Retrofit尝试把PHP返回的空字符串(或默认输出)解析成Lost对象,自然就抛出了Expected BEGIN_OBJECT but was STRING的异常。
解决方案(修改Java代码适配PHP)
既然你无法修改PHP,那我们调整Retrofit的请求方式,让它发送PHP期望的表单格式数据:
1. 修改Retrofit接口
把@Body换成@FormUrlEncoded和@Field,逐个传递字段:
@FormUrlEncoded @POST("post_lost_pet.php") Call<ResponseBody> postLost( @Field("name") String name, @Field("breed") String breed, @Field("type") String type, @Field("description") String description, @Field("pictures") String pictures, @Field("location") String location, @Field("locality") String locality, @Field("userid") String userid );
这里用ResponseBody作为返回类型,因为你的PHP代码没有返回任何JSON结构的响应,不需要强行解析成Lost对象。
2. 调整postLost方法实现
更新调用逻辑,传递Lost对象的各个字段,并合理处理响应:
public void postLost(Lost pet, final IClient client){ Call<ResponseBody> call = retrofitInit().postLost( pet.getName(), pet.getBreed(), pet.getType(), pet.getDescription(), pet.getPictures(), pet.getLocation(), pet.getLocality(), pet.getUserid() ); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if(response.isSuccessful()){ // 请求成功执行,PHP完成插入操作 client.lostCallback(); } else { // 处理HTTP错误(比如4xx/5xx状态码) client.lostFailure("Request failed with code: " + response.code()); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { client.lostFailure(t.toString()); } }); }
额外说明(PHP代码的问题,供你参考)
虽然你不能修改PHP,但还是提一下它的两处问题:
- 代码里同时用了
bindParam和execute传递参数,属于冗余操作,二选一即可 - 执行完插入后没有返回任何响应(比如JSON格式的成功/失败标记),这也是导致Retrofit解析失败的直接诱因
内容的提问来源于stack exchange,提问作者Paula Daniela
相关产品推荐
相关产品推荐

