Retrofit 和 Moshi:如何处理 com.squareup.moshi.JsonDataException

Gab*_*rin 6 android

此场景发生在使用 Retrofit2 和 Moshi 进行 JSON 反序列化的 Android 应用程序中。

在您无法控制服务器的实现的情况下,并且这表示服务器在响应请求的方式上有不一致的行为(也称为“坏情况”):

有没有办法处理 com.squareup.moshi.JsonDataException 而不崩溃?

例如,您期望一个 JSONArray,但这里出现了一个 JSONObject。碰撞。除了让应用程序崩溃之外,还有其他方法可以解决这个问题吗?

另外,在服务器的实现被更新的情况下,向用户显示一条错误消息,而不是让它崩溃/完全停止服务,即使是一个错误的请求,不是更好吗?

XME*_*XME 1

使用 Retrofit 进行调用并使用 try 和 catch 来处理异常,类似于:

class NetworkCardDataSource(
private val networkApi: NetworkCardAPI,
private val mapper: CardResponseMapper,
private val networkExceptionMapper: RetrofitExceptionMapper,
private val parserExceptionMapper: MoshiExceptionMapper
) : RemoteCardDataSource {

override suspend fun getCard(id: String): Outcome<Card, Throwable> = withContext(Dispatchers.IO) {
    val response: Response<CardResponseJson>
    return@withContext try {
        response = networkApi.getCard(id)
        handleResponse(
            response,
            data = response.body(),
            transform = { mapper.mapFromRemote(it.card) }
        )
    } catch (e: JsonDataException) {
        // Moshi parsing error
        Outcome.Failure(parserExceptionMapper.getException(e))
    } catch (e: Exception) {
        // Retrofit error
        Outcome.Failure(networkExceptionMapper.getException(e))
    }
}

private fun <Json, D, L> handleResponse(response: Response<Json>, data: D?, transform: (D) -> L): Outcome<L, Throwable> {
    return if (response.isSuccessful) {
        data?.let {
            Outcome.Success(transform(it))
        } ?: Outcome.Failure(RuntimeException("JSON cannot be deserialized"))
    } else {
        Outcome.Failure(
            HTTPException(
                response.message(),
                Exception(response.raw().message),
                response.code(),
                response.body().toString()
            )
        )
    }
}
}
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • networkApi是你的 Retrofit 对象,
  • mapper是一个类,用于将接收到的对象映射到应用程序中使用的另一个对象(如果需要),
  • networkExceptionMapper并将parserExceptionMapperRetrofit 和 Moshi 异常分别映射到您自己的异常,以便 Retrofit 和 Moshi 异常不会遍布您的应用程序(如果需要),
  • Outcome只是一个 iOSResult枚举副本,用于返回成功或失败结果,但不能同时返回两者,
  • HTTPException是一个自定义运行时异常,用于返回不成功的请求。

这是一个干净的架构示例项目的片段。