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

时间:2016-09-10 09:19:30

标签: android

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

如果您无法控制服务器的实现,并且此服务器在响应请求方面的行为不一致(也称为“不良案例”):

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

例如,你期望一个JSONArray,这里有一个JSONObject。崩溃。还有另一种方法可以解决这个问题,然后让应用程序崩溃吗?

同样在服务器的实现更新的情况下,向用户显示错误消息不是更好,而不是让它崩溃/完全停止服务,即使对于一个错误的请求也是如此?

1 个答案:

答案 0 :(得分:0)

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

starting offset

哪里:

  • 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() ) ) } } } 是您的 Retrofit 对象,
  • networkApi 是一个类,用于将接收到的对象映射到应用中使用的另一个对象(如果需要),
  • mappernetworkExceptionMapper 分别将 Retrofit 和 Moshi 异常映射到您自己的异常,以便 Retrofit 和 Moshi 异常不会遍布您的应用(如果需要),
  • parserExceptionMapper 只是一个 iOS Outcome 枚举副本,用于返回成功或失败结果,但不能同时返回两者,
  • Result 是返回不成功请求的自定义运行时异常。

这是来自 clean architecture example project 的片段。