使用Retrofit+Moshi+Kotlin捕获并上报服务端错误JSON
精准捕获JSON解析异常并记录错误JSON
针对你遇到的Crashlytics中偶发的必填字段缺失崩溃,以下是几种精准捕获错误并记录对应JSON的方案,既不用把所有字段设为可空,也不会产生全量日志:
1. 单个解析点包裹Try-Catch(基础方案)
根据你使用的JSON解析库,在解析逻辑外层包裹try-catch,捕获必填字段缺失的异常,同时上报原始JSON:
针对Gson
fun <T> parseWithGson(json: String, targetType: Type): T? { return try { Gson().fromJson(json, targetType) } catch (e: JsonSyntaxException) { // 上报至Firebase事件 FirebaseAnalytics.getInstance().logEvent("json_parse_failure", bundleOf( "error_detail" to e.message.orEmpty(), "raw_json" to json )) // 同时保留Crashlytics崩溃记录 FirebaseCrashlytics.getInstance().recordException(e) // 若不需要避免崩溃,可直接抛出异常 throw e } }
针对Moshi
Moshi中必填字段缺失会抛出JsonDataException,处理逻辑类似:
val moshi = Moshi.Builder().build() fun <T> parseWithMoshi(json: String, targetType: Type): T? { val adapter = moshi.adapter<T>(targetType) return try { adapter.fromJson(json) } catch (e: JsonDataException) { FirebaseAnalytics.getInstance().logEvent("json_parse_failure", bundleOf( "error_detail" to e.message.orEmpty(), "raw_json" to json )) FirebaseCrashlytics.getInstance().recordException(e) throw e } }
2. Retrofit全局拦截(网络请求场景)
如果崩溃来自Retrofit接口的JSON解析,可以自定义ConverterFactory,全局拦截解析异常并上报:
自定义Gson Converter
class SafeGsonConverterFactory(private val gson: Gson) : Converter.Factory() { override fun responseBodyConverter( type: Type, annotations: Array<Annotation>, retrofit: Retrofit ): Converter<ResponseBody, *>? { val delegateAdapter = gson.getAdapter(TypeToken.get(type)) return Converter { responseBody -> val rawJson = responseBody.string() return@Converter try { delegateAdapter.fromJson(rawJson) } catch (e: JsonSyntaxException) { // 额外上报请求URL,方便定位接口 FirebaseAnalytics.getInstance().logEvent("retrofit_parse_failure", bundleOf( "error_detail" to e.message.orEmpty(), "raw_json" to rawJson, "request_url" to "${retrofit.baseUrl()}${(retrofit.requestFactory()?.toString() ?: "")}" )) FirebaseCrashlytics.getInstance().recordException(e) throw e } finally { responseBody.close() } } } companion object { fun create(gson: Gson = Gson()): SafeGsonConverterFactory { return SafeGsonConverterFactory(gson) } } }
替换Retrofit默认Converter
val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(SafeGsonConverterFactory.create()) // 其他配置 .build()
关键说明
- 以上方案只会在解析出错时记录对应的JSON,不会产生全量请求日志,避免日志臃肿
- 若需要保持原有崩溃行为,捕获异常后重新抛出即可,Crashlytics仍会收到崩溃报告,同时你能拿到错误JSON用于反馈给服务端
- 可以根据需求选择上报到自有服务端或Firebase事件,核心是保留原始错误JSON和异常信息
内容的提问来源于stack exchange,提问作者HBB20
相关产品推荐
相关产品推荐

