Android应用通过Retrofit2调用API接收ByteArray时报错如何解决
报错原因
你当前的Retrofit全局配置了GsonConverterFactory,Gson会默认将所有接口的返回内容都当做JSON格式解析,而你请求的图片接口返回的是二进制字节流,不符合JSON格式要求,两次报错本质都是Gson解析二进制内容失败导致的:
- 第一次指定
Response<ByteArray>时,Gson尝试将返回内容解析为JSON数组,找不到JSON数组的起始标识[,所以抛出Expected BEGIN_ARRAY but was STRING异常 - 第二次修改为
Response<String>时,Gson尝试将返回内容解析为JSON字符串,二进制内容不符合JSON语法规则,所以抛出MalformedJsonException异常
解决方案
方案1:用ResponseBody接收二进制流(推荐)
直接使用OkHttp原生的ResponseBody接收二进制数据,不需要经过Gson解析,步骤如下:
- 修改API接口,添加
@Streaming注解,响应类型改为Response<ResponseBody>:
@Streaming // 大文件建议加此注解,避免一次性全量加载进内存 @GET("api/getImage") suspend fun getImage(@Query("user_id") user_id: String): Response<ResponseBody>
- 在Repository层从ResponseBody中取出字节数组:
suspend fun getImage(user_id: String): ByteArray? { val response = RetrofitInstance.api.getImage(user_id) return if (response.isSuccessful) { response.body()?.bytes() } else { // 可自行添加请求失败的处理逻辑 null } }
方案2:配置多ConverterFactory(适合同一个Retrofit实例同时对接JSON接口和二进制接口的场景)
在构建Retrofit实例时,先添加ScalarsConverterFactory再添加GsonConverterFactory,让非JSON格式的响应优先被Scalars转换器处理:
- 先引入Scalars转换器依赖(build.gradle):
implementation "com.squareup.retrofit2:converter-scalars:2.9.0" // 版本和你Retrofit版本保持一致即可
- 修改Retrofit配置:
private val retrofit by lazy { val gson = GsonBuilder().setLenient().create() Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(ScalarsConverterFactory.create()) // 排在Gson前面 .addConverterFactory(GsonConverterFactory.create(gson)) .build() }
修改后你之前声明Response<String>的写法也可以正常运行,拿到字符串后自行转成字节数组即可。
内容的提问来源于stack exchange,提问作者coderperz
相关产品推荐
相关产品推荐

