3

I have SpringBoot Java (server stub) code generated from a YAML API definition file which I coded in SwaggerHub. I use Open API 3.

I cannot get this generated code working, seems quite buggy.

The error I cannot fix is this one:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.OffsetDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.swagger.v3.oas.models.OpenAPI["components"]->io.swagger.v3.oas.models.Components["schemas"]->java.util.TreeMap["CancelData"]->io.swagger.v3.oas.models.media.ObjectSchema["properties"]->java.util.TreeMap["dateStamp"]->io.swagger.v3.oas.models.media.DateTimeSchema["example"])
        at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.13.1.jar!/:2.13.1]
        at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300) ~[jackson-databind-2.13.1.jar!/:2.13.1]
        at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35) ~[jackson-databind-2.13.1.jar!/:2.13.1]
        

I get it when I git the API docs URL.

localhost:8080/.../api-docs

I tried all suggestion which I could find on the web but nothing helps.

I think it's related to this field which I have in my YAML file.

dateStamp:
      type: string
      format: date-time
      description: The creation date and time of this cancel transaction
      example: "2022-01-28T05:03:57Z"

I tried registering JavaTimeModule and all that was suggested on the web. I don't understand this error. I don't know even if I am putting this in the right place. But this is the fix I tried.

@Bean
ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    return objectMapper;
}

I put it in the SwaggerDocumentationConfig.

In general, I don't understand why this generated code is so buggy.

https://github.com/FasterXML/jackson-modules-java8/issues/219
serialize/deserialize java 8 java.time with Jackson JSON mapper

How should I fix this?

peter.petrov
  • 38,363
  • 16
  • 94
  • 159

3 Answers3

1

I ran into a similar issue earlier today. Looking at the jackson-datatype-jsr310 term, I came across https://geowarin.com/correctly-handle-jsr-310-java-8-dates-with-jackson/

In it, it suggests adding

    compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'

which I did using this:

    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:+'

What you can then do when creating your ObjectMapper is replace

@Bean
ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    return objectMapper;
}

with

@Bean
ObjectMapper objectMapper(Jackson2ObjectMapperBuilder objectMapperBuilder) {
    objectMapperBuilder.createXmlMapper(false).build();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    return objectMapper;
}
Trec Apps
  • 221
  • 2
  • 9
1

The reason, why @Bean ObjectMapper doesnt work, is because swagger dont use Spring context beans, but initiate mapper by itself statically as a singleton. So you may get this mapper and configure it as you need by calling:

io.swagger.util.Json.mapper().registerModule(new JavaTimeModule());

Do it before swagger beans initialization.

1

I had the same error.

Remove the example (only for dates) which will be automatically generated.

dateStamp: type: string format: date-time description: The creation date and time of this cancel transaction example: "2022-01-28T05:03:57Z"

If you prefer to use example

Try to create a class like this, it worked for me

package org.openapitools.configuration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;

@Configuration
public class JacksonModuleConfiguration implements JacksonModuleRegistrar {

    @Override
    public void maybeRegisterModule(ObjectMapper mapper) {
        mapper.registerModule(new JavaTimeModule());
    }
}