Description

When customizing Jackson's ObjectMapper via Jackson2ObjectMapperBuilderCustomizer in Spring Boot, attempting to configure JsonReadFeatures like below causes IllegalArgumentException:

import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;

@Slf4j
@AutoConfiguration(before = JacksonAutoConfiguration.class)
public class JacksonConfig {
    @Bean
    private Jackson2ObjectMapperBuilderCustomizer customize() {
        return builder -> {
            builder.featuresToEnable(JsonReadFeature.ALLOW_SINGLE_QUOTES);
            builder.featuresToEnable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS);
            builder.featuresToEnable(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN);
        };
    }
}

This is because Jackson2ObjectMapperBuilder currently only supports configuring a limited set of feature types including JsonParser.Feature, JsonGenerator.Feature, SerializationFeature, DeserializationFeature and MapperFeature. But JsonReadFeature, JsonWriteFeature, StreamWriteFeature introduced in Jackson 2.10 is not supported yet. So enabling it via customize() method throws exception: IllegalArgumentException: Unknown feature class: com.fasterxml.jackson.core.json.JsonReadFeature
IllegalArgumentException: Unknown feature class: com.fasterxml.jackson.core.json.JsonWriteFeature IllegalArgumentException: Unknown feature class: com.fasterxml.jackson.core.json.StreamWriteFeature

Root Cause

private void configureFeature(ObjectMapper objectMapper, Object feature, boolean enabled) {
    if (feature instanceof JsonParser.Feature jsonParserFeature) {
        objectMapper.configure(jsonParserFeature, enabled);
    } else if (feature instanceof JsonGenerator.Feature jsonGeneratorFeature) {
        objectMapper.configure(jsonGeneratorFeature, enabled);
    } else if (feature instanceof SerializationFeature serializationFeature) {
        objectMapper.configure(serializationFeature, enabled);
    } else if (feature instanceof DeserializationFeature deserializationFeature) {
        objectMapper.configure(deserializationFeature, enabled);
    } else if (feature instanceof MapperFeature mapperFeature) {
        objectMapper.configure(mapperFeature, enabled);
    } else {
        throw new IllegalArgumentException("Unknown feature class: " + feature.getClass().getName());
    }
}

The root cause is org.springframework.http.converter.json.Jackson2ObjectMapperBuilder#configureFeature() method hardcoded checking for those feature types but not handling JsonReadFeature, JsonWriteFeature, JsonWriteFeature.

Versions

This issue occurs on latest Spring Boot 3.1.3 with Jackson 2.15.2.

Suggestion

It is suggested that Spring Framework should add support for JsonReadFeature, JsonWriteFeature, StreamWriteFeature in a future release by mapping it to corresponding MapperFeature, or identifying their parent classes like JacksonFeature and ConfigFeature, to maintain compatibility with latest Jackson versions when customizing ObjectMapper.

Comment From: sdeleuze

Jackson2ObjectMapperBuilder supports what ObjectMapper#configure supports, we can add new overloaded variants supported on more recent versions of Jackson like we did for DatatypeFeature in #31380, but I am not sure Jackson2ObjectMapperBuilder should do opinionated processing of features that ObjectMapper don't support directly.

The features you mentioned seems handled on ObjectWriter and ObjectReader side, but not directly on ObjectMapper if I am not mistaken since no facility is provided for FormatFeature, StreamWriteFeature or JacksonFeature. Could be on purpose or not.

I would suggest to create a related issue or PR on Jackson side, in order to allow Spring to support what you ask if adding those variants make sense on Jackson side. Any thoughts?

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.