Retrofit报错expected begin_array but was string问题求助(附代码)
解决Retrofit的"expected begin_array but was string"错误
你遇到的这个错误其实很常见,核心矛盾是你的Retrofit代码期望接口返回一个JSON数组,但PHP接口实际返回的是单个JSON对象。咱们一步步来解决:
错误根源分析
看你的PHP代码最后返回的内容:
$response = array('Name' => "Rami",'Age' => "24",'Phone' => "01004562638",'Email' => "24"); echo json_encode($response);
这段代码输出的JSON是单个对象:
{"Name":"Rami","Age":"24","Phone":"01004562638","Email":"24"}
但你的Retrofit接口定义的是返回List<Details_Pojo>,也就是期望一个JSON数组(格式应该是[{"Name":"Rami",...}]),所以Gson解析时就会抛出"expected begin_array but was string"的错误。
两种解决方案
方案1:修改PHP接口,返回JSON数组(推荐,适合未来扩展多条数据)
只需要把PHP里的$response改成数组包裹的形式,这样输出的就是符合Retrofit期望的数组格式:
// 用数组包裹单个对象,变成数组格式 $response = array(array('Name' => "Rami",'Age' => "24",'Phone' => "01004562638",'Email' => "24")); echo json_encode($response);
修改后,你的现有Retrofit和Activity代码不需要任何改动,就能正常解析数据。
方案2:修改Retrofit代码,适配单个对象(如果确定只会返回一条数据)
如果你的业务场景确实只会返回一条数据,也可以调整Retrofit的定义来匹配PHP的返回格式:
- 修改Api接口:把返回类型从
Call<List<Details_Pojo>>改成Call<Details_Pojo>
public interface Api { String BASE_URL = "http://10.0.2.2/retrofitapp/"; @GET("fetch_data.php") Call<Details_Pojo> getstatus(); // 移除List包裹 }
- 修改MainActivity的fetchData方法:同步调整Call类型和解析逻辑
private void fetchData() { OkHttpClient client = new OkHttpClient(); Gson gson = new GsonBuilder() .setLenient() .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(Api.BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); Api api = retrofit.create(Api.class); // 调整Call类型为单个Details_Pojo Call<Details_Pojo> call = api.getstatus(); call.enqueue(new Callback<Details_Pojo>() { @Override public void onResponse(Call<Details_Pojo> call, Response<Details_Pojo> response) { Details_Pojo details = response.body(); // 先判空避免空指针 if(details != null){ String name = details.getName(); String age = details.getAge(); String phone = details.getPhone(); String email = details.getEmail(); nametxt.setText(name); agetxt.setText(age); phonetxt.setText(phone); emailtxt.setText(email); } } @Override public void onFailure(Call<Details_Pojo> call, Throwable t) { Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
额外的PHP代码优化建议
顺便提一下你PHP代码里的两个小问题,避免后续踩坑:
- SQL注入风险:直接把
$_GET参数拼到SQL语句里非常危险,建议使用MySQLi预处理语句来避免注入。 - 语法错误:插入语句里的
$email没有加单引号,会导致SQL语法错误,应该改成:
$sql = "insert into login_info(name, age, phone, email) VALUES ('$name', '$age', '$phone','$email')";
内容的提问来源于stack exchange,提问作者Rami Alamir
相关产品推荐
相关产品推荐

