Ktor с сериализацией kotlinx: как использовать JSON.nonstrict
Я пытаюсь инициализировать клиент Ktor http и настроить сериализацию JSON. Мне нужно разрешить нестрогую десериализацию, которую позволяет объект JSON.nonstrict. Просто не могу понять, как применить этот параметр к сериализатору.
val client = HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
}
11 ответов
Вы можете указать конфигурации json с помощью построителя Json, который вы передаете в KotlinxSerializer.
val client = HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer(Json {
isLenient = true
ignoreUnknownKeys = true
})
}
}
Точные поля для построителя Json являются экспериментальными и могут быть изменены, поэтому ознакомьтесь с исходным кодом здесь.
После выхода Kotlin 1.4.0:
val response = Json {
ignoreUnknownKeys = true
}
.decodeFromString(ResponseObject.serializer(), jsonString)
А вы httpClient:
HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
}
Разобрался - можем перейти в конструктор:
serializer = KotlinxSerializer(JSON.nonstrict)
Это очень часто меняется, но с Kotlin 1.4.10 и Ktor 1.4.1 вам нужно передать kotlinx Json (будьте осторожны, потому что также есть
io.ktor.client.features.json.Json
, Я использовал псевдоним импорта, чтобы различать их, потому что мне нужны были оба
import kotlinx.serialization.json.Json as KotlinJson
)
val client = HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer(KotlinJson { ignoreUnknownKeys = true })
}
...
Для тех, кто использует дооснащение, вы можете рассмотреть возможность использования JsonConfiguration(strictMode = false)
на застройщиках.
Например:
// your retrofit builder
Retrofit.Builder()
.baseUrl(url)
.client(okHttpClient)
.client(httpClient)
.addConverterFactory(
Json(JsonConfiguration(strictMode = false))
.asConverterFactory(MediaType.get("application/json")
)
)
Источник: выпуск на github kotlinx
В версии "1.0.0RC" использование дооснащения выглядит следующим образом.
Retrofit.Builder()
.client(okHttpClient)
.baseUrl(Env.BASE_URL)
.addConverterFactory(Json{
isLenient = true
ignoreUnknownKeys = true
}.asConverterFactory(MediaType.get("application/json")))
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
Для ктор 2.0+
return HttpClient(CIO) {
engine {
maxConnectionsCount = 10
}
install(ContentNegotiation) {
json(kotlinx.serialization.json.Json {
ignoreUnknownKeys = true
})
}
install(HttpTimeout) {
requestTimeoutMillis = 1000L
connectTimeoutMillis = 1000L
socketTimeoutMillis = 1000L
}
}
Исходя из ответа Родиона Альтшулера выше, это то, что сработало для меня в моем проекте KMP:
install(JsonFeature) {
serializer = KotlinxSerializer(kotlinx.serialization.json.Json(JsonConfiguration.Stable.copy(strictMode = false))).apply {
useDefaultTransformers = true
}
}
Вроде для 1.4.32 у меня так:
install(JsonFeature) {
serializer = KotlinxSerializer(json = kotlinx.serialization.json.Json {
isLenient = true
ignoreUnknownKeys = true
})
}
Вот как вы можете настроить JsonConfig для реактивного веб-клиента Spring:
val json = Json { ignoreUnknownKeys = true isLenient = true }
val strategies = ExchangeStrategies
.builder()
.codecs { clientDefaultCodecsConfigurer ->
run {
clientDefaultCodecsConfigurer.defaultCodecs()
.kotlinSerializationJsonDecoder(KotlinSerializationJsonDecoder(json))
clientDefaultCodecsConfigurer.defaultCodecs()
.kotlinSerializationJsonEncoder(KotlinSerializationJsonEncoder(json))
}
}.build()
return WebClient
.builder()
.exchangeStrategies(strategies)
.baseUrl(baseUrl!!)
.build()
Модернизация принимает только клиентов типа okhttp
Невозможно передать, например, org.springframework.web.reactive.function.client.Webclient?
Насколько я знаю
val response = Json {
ignoreUnknownKeys = true
}
.decodeFromString(ResponseObject.serializer(), jsonString)
Это должно управляться для соответствующего класса @Serialiazble, верно?
Нет ли другого варианта в Kotlin + Spring Webflux для решения этой проблемы вместо использования, например, сопоставления объектов Jackson или необходимости реализации этого для соответствующего объекта @Serializable для игнорирования неизвестных ключей при использовании Spring Webclient?