Jackson MismatchedInputException for successful response with no body, after migrating to Unirest 4
j-mew-s opened this issue · 2 comments
Describe the bug
Receiving a successful response (I tried 200 and 204) with no body fails deserialization. I guess this might just be a Jackson or Java Http Client issue, but it feels like a pretty basic thing. There's a fair chance I've configured something wrong!
It seems that with the Apache client, the response entity was set to null, whereas now it's set to empty string (as highlighted in the migration notes).
The impact is that previously in the ObjectResponse
constructor, the getBody
call would be skipped due to the Optional.empty, and ultimately Jackson wouldn't try to map anything. When it does, it falls over.
To Reproduce
build.gradle.kts
plugins {
kotlin("jvm") version "1.9.20"
id("java-library")
application
}
group = "co.glean"
project.setProperty("mainClassName", "co.glean.common.main.MainKt")
defaultTasks = mutableListOf("build")
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
testImplementation("com.squareup.okhttp3:mockwebserver:4.12.0")
// failing with unirest 4
implementation(platform("com.konghq:unirest-java-bom:4.1.1"))
implementation("com.konghq:unirest-java-core")
implementation("com.konghq:unirest-objectmapper-jackson")
// working with unirest 3
//implementation("com.konghq:unirest-java:3.14.2")
//implementation("com.konghq:unirest-objectmapper-jackson:3.14.4")
//implementation("com.fasterxml.jackson.core:jackson-databind:2.14.1")
//implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1")
}
tasks.test {
useJUnitPlatform()
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
TestMain.kt
import kong.unirest.core.*
//import kong.unirest.*
import com.fasterxml.jackson.databind.json.JsonMapper
import kong.unirest.jackson.JacksonObjectMapper
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.jupiter.api.Test
class TestUnirest411 {
@Test
fun `test unirest`() {
Unirest.config().objectMapper = JacksonObjectMapper(JsonMapper.builder().build())
val mockWebServer = MockWebServer()
try {
mockWebServer.start()
mockWebServer.enqueue(MockResponse().setResponseCode(204))
val response = Unirest.post(mockWebServer.url("/test").toString())
.asObject(Empty::class.java)
if (!response.isSuccess) {
val parsingException: UnirestParsingException? = response.parsingError.orElse(null)
throw Error("${response.status}", parsingException)
}
} finally {
mockWebServer.shutdown()
}
}
}
stack trace
kong.unirest.core.UnirestParsingException: kong.unirest.core.UnirestException: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
at [Source: (String)""; line: 1, column: 0]
at app//kong.unirest.core.BaseResponse.setParsingException(BaseResponse.java:97)
at app//kong.unirest.core.ObjectResponse.getBody(ObjectResponse.java:68)
at app//kong.unirest.core.ObjectResponse.lambda$new$1(ObjectResponse.java:41)
at java.base@17.0.9/java.util.Optional.map(Optional.java:260)
at app//kong.unirest.core.ObjectResponse.<init>(ObjectResponse.java:41)
at app//kong.unirest.core.BaseRequest.lambda$asObject$6(BaseRequest.java:242)
at app//kong.unirest.core.java.JavaClient.transformBody(JavaClient.java:160)
at app//kong.unirest.core.java.JavaClient.request(JavaClient.java:72)
at app//kong.unirest.core.BaseRequest.request(BaseRequest.java:341)
at app//kong.unirest.core.BaseRequest.asObject(BaseRequest.java:242)
at app//TestUnirest411.test unirest(TestMain.kt:21)
Expected behavior
No parsing exception when a 204 response has no body.
Environmental Data:
see gradle file
You are essentially asking Jackson to map "" to a "Empty" object, which it cannot do, because "" is not valid JSON.
Unirest has a method for this case called .asEmpty()
, which has no body at all. I would recommend that
Thank you for your quick response, I'll give that a try.