Skip to content

java.util.Optional deserialisation fails when using TypeFactory.defaultInstance for creating JavaType for Optional<?> #372

@mattlocker

Description

@mattlocker

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

I am using Camunda 7.21 which uses Jackson. I don't know if it's using jackson the wrong way but still I want to point out a very strange behavior in jackson when deserialising an Optional value.

Version Information

2.x (tested 2.19.x, 2.18.x,2.17.x)

Reproduction

  public static void main(String[] args)
      throws StreamReadException, DatabindException, ClassNotFoundException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new ParameterNamesModule())
        .registerModule(new Jdk8Module())
        .registerModule(new JavaTimeModule());
    mapper.enable(Feature.ALLOW_UNQUOTED_FIELD_NAMES);
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

    // works as expected
    // prints Optional.empty
    System.out.println(mapper.readValue(mapper.treeAsTokens(NullNode.getInstance()),
        Class.forName("java.util.Optional", true, Thread.currentThread().getContextClassLoader())));

    // works as expected
    {
      TextNode parameter = TextNode.valueOf("test");
      Class<?> type = Class.forName("java.util.Optional", true,
          Thread.currentThread().getContextClassLoader());
      Object value = mapper.readValue(mapper.treeAsTokens(parameter),
          type);
      System.out.println(value);
      // prints Optional[test]
    }

     // works as expected
    {
      TextNode parameter = TextNode.valueOf("test");
      JavaType type = TypeFactory.defaultInstance().constructType(Optional.class);
      Object value = mapper.readValue(mapper.treeAsTokens(parameter),
          type);
      // throws exception
      System.out.println(value);
    }
}

Here is the stacktrace:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 optional type java.util.Optional not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jdk8" to enable handling
at [Source: UNKNOWN; byte offset: #UNKNOWN]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1888)
at com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer.deserialize(UnsupportedTypeDeserializer.java:48)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4904)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3105)

Expected behavior

The last code block should work and return Optional[test].

Additional context

The error message is wrong all the way, as the Jdk8Module is in place.

I tried also with a POJO including an Optional field with the same result.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions