Analizando json con API remota rota

Aquí está mi class de model

data class Article( val id: Int? = 0, val is_local: Boolean? = false, val comments: List<Comment?>? = listOf())

y aquí está json

  { "id": 33, "is_local": "true", "comments": [ { "url": "aaa" }, { "url": "bbb" }, { "url": "ccc" ) ] } 

Estoy usando este Adaptador personalizado para devolver el valor pnetworkingeterminado en caso de error de análisis, como en mi caso es el campo is_local

 class DefaultOnDataMismatchAdapter<T> private constructor(private val delegate: JsonAdapter<T>, private val defaultValue: T?) : JsonAdapter<T>() { @Throws(IOException::class) override fun fromJson(reader: JsonReader): T? = try { delegate.fromJsonValue(reader.readJsonValue()) } catch (e: Exception) { println("Wrongful content - could not parse delegate " + delegate.toString()) defaultValue } @Throws(IOException::class) override fun toJson(writer: JsonWriter, value: T?) { delegate.toJson(writer, value) } companion object { @JvmStatic fun <T> newFactory(type: Class<T>, defaultValue: T?): JsonAdapter.Factory { return object : JsonAdapter.Factory { override fun create(requestedType: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? { if (type != requestedType) { return null } val delegate = moshi.nextAdapter<T>(this, type, annotations) return DefaultOnDataMismatchAdapter(delegate, defaultValue) } } } } } 

y mi testing falla y el valor boolean no es falso, he agregado el adaptador anterior a moshi

 @Before fun createService() { val moshi = Moshi.Builder() .add(DefaultOnDataMismatchAdapter .newFactory(Boolean::class.java,false)) .add(KotlinJsonAdapterFactory()) .build() val retrofit = Retrofit.Builder() .baseUrl(mockWebServer.url("/")) .addConverterFactory(MoshiConverterFactory.create(moshi)) .build() service = retrofit.create(ApiStores::class.java) } @Test fun getBooleanParsingError() { enqueueResponse(case1) val article = service.getArticle().execute() assert(article.body()!!).isNotNull() assert(article.body()!!.is_local).isEqualTo(false) // test fail here } 

pero cuando cambio el tipo de datos del campo is_local en la class de model para que no sea nulo, funciona

El problema es que types kotlin.Boolean y kotlin.Boolean? corresponden a 2 types de Java diferentes:

  • kotlin.Boolean es boolean tipo primitivo de Java
  • kotlin.Boolean? es java.lang.Boolean tipo de Java

En su testing, usted creó un adaptador para un kotlin.Boolean (es decir, tipo boolean Java), mientras que en su model de datos, ¿tiene un kotlin.Boolean? (es decir, un tipo java.lang.Boolean ). Por este motivo, cuando se llama a method create(...) de Factory , se encuentra en una situación en la que type != requestedType KotlinJsonAdapter , por lo que no se crea el KotlinJsonAdapter se usa KotlinJsonAdapter . En este punto, dado que el campo is_local de Json no es un boolean (sino una cadena), Moshi debería generar una exception.

Si cambia su model de datos o su adaptador para usar el mismo tipo, se encuentra en una situación en la que type == requestedType , de modo que se crea su adaptador, la exception se lanza como antes, pero agregó un bloque catch que devuelve el valor pnetworkingeterminado .

  • Convirtiendo un HashMap usando moshi
  • Clase de datos KotlinReflectionInternalError