Skip to content

Coercion shouldn't be necessary for Enums specifying an empty string #4896

@joaocanaverde-blue

Description

@joaocanaverde-blue

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

Trying to deserialise:

{ "example": "" }

Results in:

Cannot coerce empty String ("") to `YesOrNoOrEmpty` value (but could if coercion was enabled using `CoercionConfig`)

Despite an empty string ("") being listed as a value in the enum.

enum class YesOrNoOrEmpty(val value: kotlin.String) {
    @JsonProperty(value = "")
    EMPTY(""),

    @JsonProperty(value = "yes")
    YES("yes"),

    @JsonProperty(value = "no")
    NO("no");
}

I'm trying to deserialise historical values, so this is a value I have to support. Ideally I'd still like to deserialise to an enum rather than just into a string, and would like to avoid coercion if possible.

Given that I'm specifying the empty string explicitly with @JsonProperty(value = ""), I'm assuming encountering this exception is a bug rather than intended behaviour?

Version Information

2.18.2

Reproduction

Read:

{ "example": "" }

into an Example object like:

data class Example(
    val example: YesOrNo
)

enum class YesOrNo(val value: kotlin.String) {
    @JsonProperty(value = "")
    EMPTY(""),

    @JsonProperty(value = "yes")
    YES("yes"),

    @JsonProperty(value = "no")
    NO("no");
}

Expected behavior

Deserialisation works.

Additional context

A workaround does exist (as the exception message suggests):

import com.fasterxml.jackson.databind.cfg.CoercionAction
import com.fasterxml.jackson.databind.cfg.CoercionInputShape
import com.fasterxml.jackson.databind.type.LogicalType
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder

@Configuration
class JacksonConfig {
    @Bean
    fun jsonCustomizer(): Jackson2ObjectMapperBuilderCustomizer {
        return Jackson2ObjectMapperBuilderCustomizer { builder: Jackson2ObjectMapperBuilder ->
            builder.postConfigurer { objectMapper ->
                objectMapper.coercionConfigFor(LogicalType.Enum)
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.TryConvert)
            }

        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    2.19Issues planned at 2.19 or later

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions