Android Kotlin项目Moshi解析报错Expected BEGIN_ARRAY but was STRING求解
问题根因
这个报错的核心原因是PalletsPicked同步时服务端返回的响应内容不是你预期的纯JSON数组,两种报错的对应逻辑:
- 最初的
JsonEncodingException是因为响应里掺杂了JSON之外的多余内容,导致Moshi识别为非法JSON格式 - 开启lenient后Moshi放宽了解析规则,把整个带多余内容的响应当成了字符串处理,所以抛出
Expected BEGIN_ARRAY but was STRING的类型不匹配错误
Devices同步正常说明你的Moshi、Retrofit配置本身没有问题,问题集中在PalletsPicked对应的服务端处理逻辑、或者上传的PalletsPicked数据触发了服务端异常输出。
排查解决步骤
- 优先打印原始响应确认内容
临时修改Retrofit接口定义,先不做自动JSON解析,直接拿到原始响应体打印内容,确认实际返回的是什么:
// 临时修改接口用于调试 @FormUrlEncoded @POST("sync_up.php") suspend fun syncUp(@Field("table") Table: String, @Field("deviceid") DeviceID: Int, @Field("key") DeviceKey: String, @Field("data") Data: String): ResponseBody // 调用处打印完整响应 val rawResponse = SyncUpApi.retrofitService.syncUp("pallets_picked", _deviceid, _deviceKey, palletsPickedJson) Log.d("RAW_RESPONSE", "响应内容:${rawResponse.string()}")
如果打印出来的内容除了预期的JSON数组之外还有PHP报错信息、调试输出、多余的空格/换行/BOM头,直接定位对应输出的位置删除即可。
- 检查服务端PalletsPicked处理逻辑
- 确认该逻辑块内没有遗留的
echo、var_dump、print_r等调试输出代码 - 检查PHP文件开头
<?php前有没有空格、换行,文件末尾如果有?>标记建议直接删除,避免末尾多余字符被输出 - 关闭PHP错误输出或者把错误写入日志不要输出到响应体,避免触发异常时错误信息破坏JSON格式
- 输出JSON前统一加Content-Type声明:
<?php // 所有逻辑处理完成后,输出前加头声明 header('Content-Type: application/json; charset=utf-8'); echo json_encode($response);
- 验证上传数据合法性
检查你传入的palletsPickedJson是否有未转义的特殊字符、语法错误,避免服务端解析上传数据时触发异常,返回错误信息而非预期的JSON响应。
内容的提问来源于stack exchange,提问作者sonfollower
相关产品推荐
相关产品推荐

