You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
I have raised this bug in jackson-databind already, but it could require changes here too. In jackson-databind StdDeserializer.java you can find the following Coercion related code:
final CoercionAction act = _checkFromStringCoercion(ctxt, text,
LogicalType.Boolean, Boolean.TYPE);
if (act == CoercionAction.AsNull) {
_verifyNullForPrimitive(ctxt);
return false;
}
if (act == CoercionAction.AsEmpty) {
return false;
}
The problem with automatically assuming the boolean value to be "false" is that KotlinModule has a setting which allows null values to be automatically translated to property default values. See below:
val kotlinModule = KotlinModule(nullIsSameAsDefault = true)
So if you have a data class with default values such as this:
enum class LogLevel {
TRACE, DEBUG, INFO, WARN, ERROR
}
data class MapperTest(
val processName: String,
val logLevel: LogLevel = LogLevel.WARN,
val datadump: Boolean = true,
val expiration: Int = 0
)
You would expect an empty string for the "datadump" property to be deserialized to the default value "true", but instead it is deserialized to "false" because of the coercion logic shown above.
This works well with the "logLevel" enum property property though. When I pass a null value it is deserialized as the default value, which is LogLevel.WARN.
The coercion settings for ENUM are set like this and work as expected:
To Reproduce
You can reproduce this issue by adding the relevant jackson 2.12.0 dependencies (databind and kotlin module) and running the unit test below:
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.cfg.CoercionAction
import com.fasterxml.jackson.databind.cfg.CoercionInputShape
import com.fasterxml.jackson.databind.type.LogicalType
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class BooleanCoercionTest{
enum class LogLevel {
TRACE, DEBUG, INFO, WARN, ERROR
}
data class MapperTest(
val processName: String,
val logLevel: LogLevel = LogLevel.WARN,
val datadump: Boolean = true,
val expiration: Int = 0
)
@Test
fun testBooleanCoercion(){
val objectMapper = ObjectMapper()
objectMapper.registerModule(KotlinModule(nullIsSameAsDefault = true))
objectMapper.coercionConfigFor(LogicalType.Enum)
.setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull)
// Coercion to null/empty Boolean
objectMapper.coercionConfigFor(LogicalType.Boolean)
.setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull)
val value = objectMapper.readValue("""{"processName":"NAME", "logLevel":"", "datadump":""}""",MapperTest::class.java)
assertEquals(LogLevel.WARN, value.logLevel)
// Expected the value to be "true" but it is "false"
assertTrue(value.datadump)
}
}
The text was updated successfully, but these errors were encountered:
The jackson official answer is to enable DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES as the correct way to handle this (see #242 ).
Even if CoercionAction.AsNull is specified, it will eventually be converted to its default value of false by this option (CoercionAction.Fail is processed first, so it has an effect).
At least, this was closed because the behavior was caused by databind and not a kotlin-module issue.
Describe the bug
I have raised this bug in jackson-databind already, but it could require changes here too. In jackson-databind StdDeserializer.java you can find the following Coercion related code:
The problem with automatically assuming the boolean value to be "false" is that
KotlinModule
has a setting which allows null values to be automatically translated to property default values. See below:So if you have a data class with default values such as this:
You would expect an empty string for the "datadump" property to be deserialized to the default value "true", but instead it is deserialized to "false" because of the coercion logic shown above.
This works well with the "logLevel" enum property property though. When I pass a null value it is deserialized as the default value, which is
LogLevel.WARN
.The coercion settings for ENUM are set like this and work as expected:
The coercion settings for Boolean are set like this and don't work as expected.
Version information
2.12.0
To Reproduce
You can reproduce this issue by adding the relevant jackson 2.12.0 dependencies (databind and kotlin module) and running the unit test below:
The text was updated successfully, but these errors were encountered: