Обработка исключения MissingFieldException в Kotlin Serialization с помощью дооснащения
Я использую 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 (в этом надуманном примере) намеренно опускает поле 'missing':
{"name":"me", "species":"superhuman"}
Поскольку этот json не содержит missing
поля из класса данных, приложение вылетает и выдает MissingFieldException
. Мне интересно, как избежать этой проблемы в случае модернизации.
Спасибо за любую помощь.
3 ответа
На самом деле это не может создать Person
объект из json как ваш Person
конструктор класса хочет 3 значения. Вы должны выполнить это требование для создания объекта.
Одно из возможных решений для решения этой проблемы - использовать значение по умолчанию в Kotlin следующим образом:
data class Person(
var name: String="",
var species: String="",
var missing: String="")
Другое решение - использовать несколько конструкторов с разными параметрами, но, как вы упомянули, со временем они могут отличаться, поэтому это решение может оказаться не очень удобным. Спасибо
Начиная с
kotlinx.serialization-1.3.0
, вы можете создать объект Json как
Json { explicitNulls = false }
. Это поможет сериализовать ответ с различными полями, не выбрасывая
MissingFieldException
и без необходимости передавать значения по умолчанию.
Для тех, кто уже сделал свойство обнуляемым и все еще сталкивается с проблемой, установитеexplicitNulls to false
в вашем JsonBuilder
@OptIn(ExperimentalSerializationApi::class)
val CustomJson = Json {
ignoreUnknownKeys = true
isLenient = true
explicitNulls = false
}
// usage
CustomJson.decodeFromString<Class>(jsonString)