Skip to content

Jackson 2.16 fails attempting to obtain ObjectWriter for an Enum which some value returns null from toString() #4355

@YutaHiguchi-bsn

Description

@YutaHiguchi-bsn

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

After upgrading to 2.16.1, I cannot obtain ObjectWriter for enum classes, which some of the value returns null from toString().

This used to work in 2.15.3

Version Information

2.16.0, 2.16.1

Reproduction

Following is the minimum JUnit 5 reproducer.

This works fine on 2.15.3 but exceptionally fails at assertDoesNotThrow(..) on 2.16.0 or 2.16.1.

    enum NullToStringEnum {
        ALPHA("A"),
        BETA("B"),
        UNDEFINED(null);

        private final String s;

        NullToStringEnum(String s) {
            this.s = s;
        }

        @Override
        public String toString() {
            return s;
        }
    }

    @Test
    void nullToStringEnum() {
        ObjectMapper mapper = new ObjectMapper();
        assertDoesNotThrow(() -> mapper.writerFor(NullToStringEnum.class));
        assertEquals("\"ALPHA\"", w.writeValueAsString(NullToStringEnum.ALPHA));
        assertEquals("\"UNDEFINED\"", w.writeValueAsString(NullToStringEnum.UNDEFINED));
    }

backtrace looks like:

Caused by: java.lang.IllegalStateException: Null String illegal for SerializedString
	at com.fasterxml.jackson.core.io.SerializedString.<init>(SerializedString.java:53)
	at com.fasterxml.jackson.databind.cfg.MapperConfig.compileString(MapperConfig.java:245)
	at com.fasterxml.jackson.databind.util.EnumValues.constructFromToString(EnumValues.java:136)
	at com.fasterxml.jackson.databind.ser.std.EnumSerializer.construct(EnumSerializer.java:125)
	at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.buildEnumSerializer(BasicSerializerFactory.java:1218)
	at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByPrimaryType(BasicSerializerFactory.java:428)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:235)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:174)
	at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1525)
	at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1493)
	at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:619)
	at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:901)
	at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.forRootType(ObjectWriter.java:1535)
	at com.fasterxml.jackson.databind.ObjectWriter.<init>(ObjectWriter.java:116)
	at com.fasterxml.jackson.databind.ObjectMapper._newWriter(ObjectMapper.java:838)
	at com.fasterxml.jackson.databind.ObjectMapper.writerFor(ObjectMapper.java:4135)
	at org.example.MainTest.lambda$nullToStringEnum$0(MainTest.java:31)
	at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:71)

Expected behavior

Be able to serialize Enums even though it's #toString() returns null

Additional context

Returning null from toString() is probably bad practice, but such Enums are out there in the wild.

From the 2.16.1 backtrace, it seems to be related to the change #4039

Building EnumValues valuesByToString regardless of the SerializationFeature.WRITE_ENUMS_USING_TO_STRING config might be the issue?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions