2

Firstly let me past some runnable code to help you get the issue I want to solve:

(maven dependency to include if you want to run this example code)

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
    <version>2.9.4.1</version>
</dependency>

simply create a Kotlin file and past the runnable code below in:

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue

data class MapObject(val map: Map<String, String>, val age: Int)
data class SimpleObject(val name:String, val age: Int)
data class MapSimpleObject(val map: SimpleObject, val age: Int)

fun main(args: Array<String>) {
    val mapper = jacksonObjectMapper()

    val mObj: MapObject = mapper.readValue("""{"map": {"name": null}, "age": 1}""")
    println(mObj)  // mObj can be created, print "MapObject(map={name=null}, age=1)", which is not nice

    val msObj: MapSimpleObject = mapper.readValue("""{"map": {"name": null, "age": 1}, "age": 1}""")
    println(msObj)  // throw MissingKotlinParameterException at line above, which is nice

    val sObj: SimpleObject = mapper.readValue("""{"name": null, "age": 1}""")
    println(sObj)  // throw MissingKotlinParameterException at line above, which is nice

    // val m: Map<String, Int> = mapOf(null to 2)  // won't compile, which is nice
}

As you can see, specifically for val mObj: MapObject, even MapObject's map is a Map defined in Kotlin with Non-Null Types, one can still create object with Json payload such as {"map": {"name": null}, "age": 1}, resulting mObj object as MapObject(map={name=null}, age=1)

This is not what I wanted, I would like Kotlin's null safety feature to capture this and throw me some exceptions if I put json payload like that.

So how can I make sure null is not injected if I have data class structure like data class MapObject(val map: Map<String, String>, val age: Int)?

Fuyang Liu
  • 1,496
  • 13
  • 26
  • 1
    cool, after huge searching I could'n find any possibility to avoid this behaviour. `@JsonSetter(contentNulls = Nulls.FAIL, nulls = Nulls.FAIL)` must enable failing on null (if I understand it right) but it don't. So I see two possible solutions: 1) deserialise with null values and after filter it 2) write custom deserialisation – kurt Jun 01 '18 at 14:50
  • I was going to suggest similar stuff as kurt mentions: Create an extension function that checks for nulls previous to read value. That's the only idea and as @jingx mentions, there's no way to avoid nulls via reflection. – Sierisimo Jun 01 '18 at 17:31

1 Answers1

2

IIUC, Kotlin's null safety is mostly compile-time. There is nothing preventing null from being set into a non-nullable property at runtime via reflection, as Kotlin reference states:

...The only possible causes of NPE's may be:

Java interoperation: ... Generic types used for Java interoperation with incorrect nullability, e.g. a piece of Java code might add null into a Kotlin MutableList, meaning that MutableList should be used for working with it;

jingx
  • 3,698
  • 3
  • 24
  • 40