18

I'm trying to initialize Ktor http client and setup json serialization. I need to allow non-strict deserialization which JSON.nonstrict object allows. Just can't get how to apply this setting to serializer.

 val client = HttpClient {
                install(JsonFeature) {
                    serializer = KotlinxSerializer()                    
                }
        }
Rodion Altshuler
  • 1,713
  • 1
  • 15
  • 31

10 Answers10

15

You can specify json configurations using the Json builder, which you pass into the KotlinxSerializer.

val client = HttpClient {
    install(JsonFeature) {
        serializer = KotlinxSerializer(Json {
            isLenient = true
            ignoreUnknownKeys = true
        })                    
    }
}

The exact fields for the Json builder is experimental and subject to change, so check out the source code here.

Jacques.S
  • 3,262
  • 2
  • 21
  • 27
12

After Kotlin 1.4.0 released:

use this for converting string to Object:

val response = Json {
    ignoreUnknownKeys = true
}.decodeFromString(ResponseObject.serializer(), jsonString)

And for your httpClient use:

HttpClient {
    install(JsonFeature) {
        serializer = KotlinxSerializer()
    }
    install(Logging) {
        logger = Logger.DEFAULT
        level = LogLevel.ALL
    }
}
sud007
  • 5,824
  • 4
  • 56
  • 63
Dr.jacky
  • 3,341
  • 6
  • 53
  • 91
  • Thanks it worked! So, I am already doing this in Network Layer in for HTTP client but the first one with `decodeFromString` was really helpful as I needed this for a String conversion to model. – sud007 Feb 01 '22 at 15:46
11

Figured out - we can pass in constructor:

serializer = KotlinxSerializer(Json.nonstrict)
xsveda
  • 17,074
  • 2
  • 16
  • 16
Rodion Altshuler
  • 1,713
  • 1
  • 15
  • 31
6

This change very often, but with Kotlin 1.4.10 and Ktor 1.4.1 you need to pass a kotlinx Json (be careful because there is also a io.ktor.client.features.json.Json, I used an import alias to distinguish them because I needed both import kotlinx.serialization.json.Json as KotlinJson)

val client = HttpClient {
    install(JsonFeature) {
        serializer = KotlinxSerializer(KotlinJson { ignoreUnknownKeys = true })
    }
    ...
Max Cruz
  • 1,215
  • 13
  • 17
5

For those who use retrofit, you might want to consider using JsonConfiguration(strictMode = false) on the retrofit builder.

E.g:

// your retrofit builder
Retrofit.Builder()
        .baseUrl(url)
        .client(okHttpClient)
        .client(httpClient)
        .addConverterFactory(
          Json(JsonConfiguration(strictMode = false))
              .asConverterFactory(MediaType.get("application/json")
        )
)

Source: issue on the kotlinx github

mochadwi
  • 1,190
  • 9
  • 32
  • 87
4

With the "1.0.0RC" version, the use with retrofit is as follows.

Retrofit.Builder()
        .client(okHttpClient)
        .baseUrl(Env.BASE_URL)
        .addConverterFactory(Json{
            isLenient = true
            ignoreUnknownKeys = true
        }.asConverterFactory(MediaType.get("application/json")))
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .build()
fevziomurtekin
  • 192
  • 1
  • 3
  • 10
3

Working from Rodion Altshuler's answer above, this is what worked for me in my KMP project:

install(JsonFeature) {
    serializer = KotlinxSerializer(kotlinx.serialization.json.Json(JsonConfiguration.Stable.copy(strictMode = false))).apply {
      useDefaultTransformers = true
    }
}
Joshua Kaden
  • 1,210
  • 11
  • 16
2

This is how you can configure the JsonConfig for the Spring reactive Webclient:



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()
bluecheese
  • 41
  • 3
2

It seems that for 1.4.32 I have it as follows:

install(JsonFeature) {
                    serializer = KotlinxSerializer(json = kotlinx.serialization.json.Json {
                        isLenient = true
                        ignoreUnknownKeys = true
                    })
                }
Vojtěch Sázel
  • 538
  • 6
  • 22
2

For ktor 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
            }
        }
Hett
  • 3,484
  • 2
  • 34
  • 51