Retrofit解析JSON报错:Expected BEGIN_ARRAY but was BEGIN_OBJECT问题解决
解决Gson解析错误:"Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $"
问题背景
作为Android开发者首次遇到上述Gson解析错误,怀疑问题出在Model层或数据适配逻辑中。
接口响应(Postman返回)
{ "Status": 200, "Message": "OK", "Data": { "ServiceTypes": [ { "Id": 1, "ServiceTypeNameAr": "صيانة", "ServiceTypeNameEn": "Maintenance", "MainServices": [ { "Id": 11, "ServiceTypeId": 1, "MainServiceNameAr": "تكييفات\r\n", "MainServiceNameEn": "Air conditioning\r\n", "SubServices": null }, { "Id": 12, "ServiceTypeId": 1, "MainServiceNameAr": "كهرباء\r\n", "MainServiceNameEn": "Electricity\r\n", "SubServices": null }, { "Id": 14, "ServiceTypeId": 1, "MainServiceNameAr": "سباكة", "MainServiceNameEn": "Plumbing\r\n", "SubServices": null }, { "Id": 15, "ServiceTypeId": 1, "MainServiceNameAr": "اجهزة منزلية\r\n", "MainServiceNameEn": "Home appliances\r\n", "SubServices": null } ] } ] } }
现有Model与接口代码
ResponseModel
public class ResponseModel { @SerializedName("Status") public int Status; @SerializedName("Message") public String Message; @SerializedName("Data") public DataModel Data; public int getStatus() { return Status; } public void setStatus(int status) { Status = status; } public String getMessage() { return Message; } public void setMessage(String message) { Message = message; } public DataModel getData() { return Data; } public void setData(DataModel data) { this.Data = data; } }
DataModel
public class DataModel { @SerializedName("Country") private List<CountryModel> countryModels; @SerializedName("Users") private List<UserModel> users; @SerializedName("Cities") private List<CityItem> cityItems; @SerializedName("ServiceTypes") private List<ServiceTypeModel> serviceTypeModels; private Map<String, Object> additionalProperties = new HashMap<String, Object>(); public List<CityItem> getCityItems() { return cityItems; } public void setCityItems(List<CityItem> cityItems) { this.cityItems = cityItems; } public List<UserModel> getUsers() { return users; } public void setUsers(ArrayList<UserModel> users) { this.users = users; } public List<CountryModel> getCountryModels() { return countryModels; } public void setCountryModels(ArrayList<CountryModel> countryModels) { this.countryModels = countryModels; } public List<ServiceTypeModel> getServiceTypeModels() { return serviceTypeModels; } public void setServiceTypeModels(List<ServiceTypeModel> serviceTypeModels) { this.serviceTypeModels = serviceTypeModels; } public void setCountryModels(List<CountryModel> countryModels) { this.countryModels = countryModels; } public void setUsers(List<UserModel> users) { this.users = users; } public Map<String, Object> getAdditionalProperties() { return additionalProperties; } public void setAdditionalProperties(Map<String, Object> additionalProperties) { this.additionalProperties = additionalProperties; } }
ServiceTypeModel
public class ServiceTypeModel { @SerializedName("Id") private int id; @SerializedName("ServiceTypeNameAr") private String serviceTypeNameAr; @SerializedName("ServiceTypeNameEn") private String serviceTypeNameEn; @SerializedName("MainServices") private List<MainServicesModel> mainServicesList; public List<MainServicesModel> getMainServicesList() { return mainServicesList; } public void setMainServicesList(List<MainServicesModel> mainServicesList) { this.mainServicesList = mainServicesList; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getServiceTypeNameAr() { return serviceTypeNameAr; } public void setServiceTypeNameAr(String serviceTypeNameAr) { this.serviceTypeNameAr = serviceTypeNameAr; } public String getServiceTypeNameEn() { return serviceTypeNameEn; } public void setServiceTypeNameEn(String serviceTypeNameEn) { this.serviceTypeNameEn = serviceTypeNameEn; } }
接口定义
public interface ServiceTypeInterface { @GET("ServiceType") Call<ResponseModel> GetServicesType(@Header("authorization") String token); @GET("ServiceType/{id}") Call<ResponseModel> GetServiceTypeById(@Path("id") int Id, @Header("authorization") String token); }
RecyclerView适配器
public class ServiceTypeAdapter extends RecyclerView.Adapter<ServiceTypeAdapter.ServiceTypeHolder> { private List<ResponseModel> serviceTypeModels = new ArrayList<>(); private final ServiceTypeListener listener; private Context context; public ServiceTypeAdapter(ServiceTypeListener listener, Context context, List<ResponseModel> serviceTypeList) { this.listener = listener; this.context = context; this.serviceTypeModels = serviceTypeList; } @NonNull @Override public ServiceTypeHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_sub_service, parent, false); return new ServiceTypeHolder(itemView); } @Override public void onBindViewHolder(@NonNull ServiceTypeHolder holder, int position) { final ResponseModel ServiceType = serviceTypeModels.get(position); holder.TxtServiceTypeName.setText(ServiceType.getData().getServiceTypeModels().get(0).getServiceTypeNameEn()); } @Override public int getItemCount() { return serviceTypeModels.size(); } public long getItemId(int position) { return position; } public void setList(List<ResponseModel> serviceTypeModels) { this.serviceTypeModels = serviceTypeModels; notifyDataSetChanged(); } public class ServiceTypeHolder extends RecyclerView.ViewHolder { TextView TxtServiceTypeName; public ServiceTypeHolder(@NonNull View itemView) { super(itemView); TxtServiceTypeName = itemView.findViewById(R.id.ServiceTypeName); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listener.onServiceTypeSelected(serviceTypeModels.get(getAdapterPosition())); } }); } } public interface ServiceTypeListener { void onServiceTypeSelected(ResponseModel serviceTypeModel); } }
问题排查
错误核心原因:Gson期望解析数组(BEGIN_ARRAY),但实际接收到的是对象(BEGIN_OBJECT)。结合代码来看,问题出在RecyclerView适配器的数据源逻辑:
- 接口返回单个
ResponseModel对象,而非List<ResponseModel>数组 - 适配器错误将
List<ResponseModel>作为数据源,且onBindViewHolder中强行取第一个元素的ServiceType,逻辑完全错误——实际要展示的是ResponseModel.Data.ServiceTypes列表
另外,代码未提供MainServicesModel定义,需确保该Model存在,否则解析MainServices数组时也会报错。
解决方案
1. 修正RecyclerView适配器
将数据源改为List<ServiceTypeModel>,直接对应接口返回的ServiceTypes列表:
public class ServiceTypeAdapter extends RecyclerView.Adapter<ServiceTypeAdapter.ServiceTypeHolder> { private List<ServiceTypeModel> serviceTypeModels = new ArrayList<>(); private final ServiceTypeListener listener; private Context context; public ServiceTypeAdapter(ServiceTypeListener listener, Context context) { this.listener = listener; this.context = context; } @NonNull @Override public ServiceTypeHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_sub_service, parent, false); return new ServiceTypeHolder(itemView); } @Override public void onBindViewHolder(@NonNull ServiceTypeHolder holder, int position) { ServiceTypeModel serviceType = serviceTypeModels.get(position); holder.TxtServiceTypeName.setText(serviceType.getServiceTypeNameEn()); } @Override public int getItemCount() { return serviceTypeModels.size(); } public long getItemId(int position) { return position; } public void setList(List<ServiceTypeModel> serviceTypeModels) { this.serviceTypeModels = serviceTypeModels; notifyDataSetChanged(); } public class ServiceTypeHolder extends RecyclerView.ViewHolder { TextView TxtServiceTypeName; public ServiceTypeHolder(@NonNull View itemView) { super(itemView); TxtServiceTypeName = itemView.findViewById(R.id.ServiceTypeName); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listener.onServiceTypeSelected(serviceTypeModels.get(getAdapterPosition())); } }); } } public interface ServiceTypeListener { void onServiceTypeSelected(ServiceTypeModel serviceTypeModel); } }
2. 修正接口调用后的数据源传递
在Retrofit回调中,取出ServiceTypes列表传给适配器:
// 示例调用代码 ServiceTypeInterface service = RetrofitClient.getInstance().create(ServiceTypeInterface.class); Call<ResponseModel> call = service.GetServicesType("your_token_here"); call.enqueue(new Callback<ResponseModel>() { @Override public void onResponse(Call<ResponseModel> call, Response<ResponseModel> response) { if (response.isSuccessful() && response.body() != null) { List<ServiceTypeModel> serviceTypes = response.body().getData().getServiceTypeModels(); serviceTypeAdapter.setList(serviceTypes); } } @Override public void onFailure(Call<ResponseModel> call, Throwable t) { // 处理失败逻辑 } });
3. 补充MainServicesModel定义
确保存在对应的MainServicesModel类,匹配接口返回的MainServices结构:
public class MainServicesModel { @SerializedName("Id") private int id; @SerializedName("ServiceTypeId") private int serviceTypeId; @SerializedName("MainServiceNameAr") private String mainServiceNameAr; @SerializedName("MainServiceNameEn") private String mainServiceNameEn; @SerializedName("SubServices") private List<Object> subServices; // 根据实际SubServices结构替换泛型 // Getter和Setter方法 public int getId() { return id; } public void setId(int id) { this.id = id; } public int getServiceTypeId() { return serviceTypeId; } public void setServiceTypeId(int serviceTypeId) { this.serviceTypeId = serviceTypeId; } public String getMainServiceNameAr() { return mainServiceNameAr; } public void setMainServiceNameAr(String mainServiceNameAr) { this.mainServiceNameAr = mainServiceNameAr; } public String getMainServiceNameEn() { return mainServiceNameEn; } public void setMainServiceNameEn(String mainServiceNameEn) { this.mainServiceNameEn = mainServiceNameEn; } public List<Object> getSubServices() { return subServices; } public void setSubServices(List<Object> subServices) { this.subServices = subServices; } }
验证要点
- 确认Retrofit配置中使用了GsonConverterFactory,且Gson实例配置正确
- 检查接口返回的JSON格式是否与Model类的
@SerializedName完全匹配 - 确保
ServiceTypes字段在DataModel中定义为List<ServiceTypeModel>,与JSON中的数组结构对应
内容的提问来源于stack exchange,提问作者Mohammad khaled
相关产品推荐
相关产品推荐

