Обработка сериализации Kotlin MissingFieldException с модернизацией - PullRequest
0 голосов
/ 11 октября 2019

Я использую kotlinx.serialization в сочетании с дооснащением . Ответ json, который я получу, зависит от того, какие атрибуты он будет содержать. В большинстве случаев модель данных в моем приложении имеет больше полей, чем я получу в ответе. Я не могу контролировать это, поэтому мне нужно обработать это в коде.

Kotlinx.serialization выдает MissingFieldException в таких случаях. Я знаю, что при использовании Json.parse вы можете обернуть его в блок try-catch и игнорировать такие ошибки. Но так как я использую Retrofit, я не вижу способа использовать этот подход:

WebService.kt

interface WebService {
    @GET("person.json")
    fun getPerson(): Call<MainActivity.Person>
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    @Serializable
    data class Person(val name: String, val species: String, val missing: String)

    @UnstableDefault
    override fun onCreate(savedInstanceState: Bundle?) {
        val mediaType = "application/json".toMediaTypeOrNull()
        mediaType?.let {
            retrofit = Retrofit.Builder()
                .addConverterFactory(Json.nonstrict.asConverterFactory(it))
                .baseUrl(baseUrl)
                .build()
        }

        webService = retrofit.create(WebService::class.java)

        GlobalScope.launch {
            val person = fetchPerson(webService)
        }
    }

    private suspend fun fetchPerson(webService: WebService): Person {
        return suspendCancellableCoroutine { cont ->
            webService.getPerson()
                .enqueue(object : Callback<Person> {
                    override fun onFailure(call: Call<Person>, t: Throwable) {
                        Log.e(t.toString(), "Unable to get api response")
                        cont.cancel(t)
                    }

                    override fun onResponse(
                        call: Call<Person>,
                        response: Response<Person>
                    ) {
                        if (response.isSuccessful) {
                            response.body()?.let { cont.resume(it) }
                        } else {
                            cont.cancel(IOException("${response.code()}: ${response.errorBody()}"))
                        }
                    }
                })
        }
    }
}

Ответ json (в этом вымышленном примере) преднамеренно опускает поле «пропущено»:

{"name":"me", "species":"superhuman"}

Поскольку этот json не содержит поля missing из класса данных, приложение вылетает и выдает MissingFieldException. Мне интересно, как избежать этой проблемы в деле модернизации.

Спасибо за любую помощь.

1 Ответ

1 голос
/ 11 октября 2019

На самом деле он не может создать Person объект из json, так как ваш конструктор класса Person хочет 3 значения. Вы должны выполнить это требование для создания объекта.

Одним из возможных решений этой проблемы является использование значения по умолчанию в Kotlin , например:

data class Person(
    var name: String="", 
    var species: String="", 
    var missing: String="") 

Другое решение -использовать несколько конструкторов с разными параметрами, но, поскольку вы упомянули, со временем они могут отличаться, поэтому это решение может оказаться не удобным. Спасибо

...