Retrofit 在不可为空的字符串上返回 null (Kotlin)
Posted
技术标签:
【中文标题】Retrofit 在不可为空的字符串上返回 null (Kotlin)【英文标题】:Retrofit returns null on a non-nullable String (Kotlin) 【发布时间】:2020-09-11 11:53:45 【问题描述】:当我遇到这个问题时,我正在用 android 开发一个应用程序,我真的不知道这是一个已知的错误还是我应该提交错误报告。代码如下:
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
data class Status(val msg: String, val integer: Int, val msg2:String)
interface API
@GET("/json/gson")
suspend fun gson(): Status
val gsonApiCalls = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://localhost:8080")
.build()
.create(API::class.java)
suspend fun main()
val result = gsonApiCalls.gson()
println(result)
result.msg2?.let(::println) ?: println("Null result!")
本地服务器代码(Ktor):
import io.ktor.application.*
import io.ktor.response.*
import io.ktor.request.*
import io.ktor.routing.*
import io.ktor.http.*
import io.ktor.gson.*
import io.ktor.features.*
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
data class StandardResponse(val msg: String, val integer: Int, val msg2:String?)
@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false)
install(ContentNegotiation)
gson
routing
get("/")
call.respondText("HELLO WORLD!", contentType = ContentType.Text.Plain)
get("/json/gson")
call.respond(StandardResponse("Hello",34, null))
结果是:
Status(msg=Hello, integer=34, msg2=null)
Null result!
上面的代码是我为测试这种行为而做的一个例子,但是当我第一次意识到这个“错误”出现在 Android 应用程序中时,我得到了 NullPointerException,我不明白为什么。
该应用程序正在使用远程节点服务器,并且发生了同样的事情。 Capture showing the linter thinks this can't be possible
如果这是一个错误,我应该将其报告给 Kotlin 还是 Retrofit?
【问题讨论】:
在您的客户端代码中,您有不可为空的val msg2:String
,但您从 ktor 发送 null
。这就是问题
是的,我知道,这是有意测试我描述的行为。问题是 Kotlin 字符串不应该为空,根据定义,如果它没有声明为字符串? (如图所示),但在这个例子中它是可能的。我想这是 Java 到 Kotlin 字符串转换的问题,但我仍然不明白这是怎么可能的。我的意思是,如果发生这种情况,不应该提前抛出异常吗?
是的,不可为空的字符串不应为空,因此当 gson 强制尝试将 null 解析为不可为空的字符串时会出现运行时异常。在编译时一切都很好,因为代码中没有任何地方可以将 null 传递给非 null 变量。但是如果你在运行时将 null 放入非 null 变量中,那么编译器就无法检查,对吧?
是的,我希望 gson 会抛出异常,但事实并非如此。它只是以某种方式将 null 解析为字符串
所以,总而言之,这不是改造、kotlin 和 gson 中的错误。如果这就是您要查找的全部内容,则会引发异常。如果您正在寻找一些解决方法,那么您必须更具体。
【参考方案1】:
我想我已经找到了答案,虽然我认为这是由语言保证的。
Why Kotlin data classes can have nulls in non-nullable fields with Gson?
【讨论】:
以上是关于Retrofit 在不可为空的字符串上返回 null (Kotlin)的主要内容,如果未能解决你的问题,请参考以下文章
错误无法为不可为空的类型返回 null:父 MyModelType 中的“字符串”(/createMyModelType/id)
错误:主体可能正常完成,导致返回“null”,但返回类型是不可为空的类型
GraphQL 查询返回错误“不能为不可为空的字段返回 null”