s3rius
08/06/2024, 10:32 AMs3rius
08/06/2024, 10:32 AM@Serializable
data class Object(val int: Int)
interface TestApi {
@GET("test")
suspend fun get(): Response<Object?>
}
null
is a valid JSON value. However, the request always fails with Unexpected JSON token at offset 0: Expected start of the object '{', but had 'n' instead at path: $ JSON input: null
.
A test that reproduces it, using MockWebServer:
@Test
fun test() = runTest {
val json = Json { }
val server = MockWebServer()
server.start()
val url = server.url("/")
val retrofit = Retrofit.Builder()
.client(OkHttpClient.Builder().build())
.baseUrl(url)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.build()
val api = retrofit.create(TestApi::class.java)
// Valid
server.enqueue(MockResponse().setBody(""" { "int": 42 } """))
assertThat(api.get().body()).isEqualTo(Object(42))
// Throws: JSON token at offset 0: Expected start of the object '{', but had 'n' instead at path: $
server.enqueue(MockResponse().setBody("""null"""))
assertThat(api.get().body()).isEqualTo(null)
}
Kotlinx.serialization itself is capable of deserializing nulls, but it depends on how it is used:
// Valid
assertThat(json.decodeFromString<Object?>("null")).isNull()
// Throws: Unexpected JSON token at offset 0: Expected start of the object '{', but had 'n' instead at path: $
assertThat(json.decodeFromString(Object.serializer(), "null")).isNull()
The Converter seems to be using the second option. Is there anything in particular I need to do to allow parsing null properly?jw
08/06/2024, 11:42 AMs3rius
08/06/2024, 12:19 PMResponse<ResponseBody>
instead and deserialize in a follow-up step.jw
08/06/2024, 3:13 PMResponse<Optional<YourType>>