Spring(Kotlin)控制器将数据类的不可为空的参数接收为null

时间:2018-11-05 22:54:34

标签: spring spring-boot kotlin nullpointerexception kotlin-null-safety

我遇到了意外错误,不确定如何处理。

我有一个像这样的数据类:

data class Payload (
  @SerializedName("id")
  var id: String
  @SerializedName("type")
  var type: String,
  @SerializedName("data")
  var data: String
)

还有一个像这样的简单Spring控制器:

@PostMapping("/some-endpoint")
fun dataHandler(@RequestBody payload: Payload): String{
    when (payload.type){
        "someType" -> {
            val result = try {
                gson.fromJson(payload.data, payloadData::class.java)
            } catch (e: Exception){
                throw BadDataException("Bad Data")
            }
            payloadProcessor.process(result, payload.id) // NPE here
        }
        "otherType" -> {
            doSomethingElseHere()
        }
    }
}

当执行到达payloadProcessor.process时,将出现空指针异常,因为id显然为空。另一方面,对象已创建,并且剩余的两个值似乎已正确填充。 如果添加检查空值的if语句,则ide会抱怨有效载荷属性永远不会为空,从而将if语句标记为冗余,但实际上并非如此。 我的印象是null安全属性是...好吧... null安全。至少我希望一旦对象被构造后,空指针异常就会发生。

我的问题是:

  • Spring如何设法创建这样的对象
  • 为什么在构造对象时未检测到
  • 处理此问题的“科特林”方法是什么,因为我不想检查所谓的空安全对象中的空参数。

1 个答案:

答案 0 :(得分:1)

问题出在Gson,而不是Spring。 Gson是为与Java一起使用而设计的,它在可空类型和不可空类型之间没有任何区别,因此无论如何,Gson都会很高兴地分配空值。

不幸的是,这里没有神奇的解决方案。您可以编写自己的TypeAdapter,在构造数据类之前显式检查null值,但是如果您有很多类,那将变得非常重复。另外,您可以创建自己的TypeAdapterFactory并使用Kotlin的反射库来检查哪些类型可以为空,哪些不能为空,但这会对性能和依赖性产生各种影响。

*有可空性注释(@ Nonnull,@ Nullable),但是Gson不会对其进行检查。