Use java.time.Instant to represent DateTime instead of OffsetDateTime
Asked Answered
I

5

40

I'm using the openApi maven plugin to generate java request/responses for a REST api.

The request has a DateTime property, when I run the generator I get the DateTime property of the attribute represented as java.time.OffsetDateTime. The problem is I have a requirement to represent the property as java.time.Instant.

This is the openApi specification for the request:

"DocumentDto" : {
      "type" : "object",
      "properties" : {
        "uuid" : {
          "type" : "string",
          "format" : "uuid"
        },
        "creationDate" : {
          "type" : "string",
          "format" : "date-time"
        }
      }
    }

The generated java request:

@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2019-05-21T13:07:21.639+02:00[Europe/Zurich]")
public class DocumentDto {
  public static final String SERIALIZED_NAME_UUID = "uuid";
  @SerializedName(SERIALIZED_NAME_UUID)
  private UUID uuid;


  public static final String SERIALIZED_NAME_TEST = "creationDate";
  @SerializedName(SERIALIZED_NAME_TEST)
  private OffsetDateTime creationDate;
}

The maven plugin setup:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>3.3.4</version>
    <executions>
        <execution>
            <id>test-service</id>
            <phase>validate</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.build.directory}/open-api/swagger.json
                </inputSpec>
                <generatorName>java</generatorName>
                <validateSpec>false</validateSpec>
                <generateApis>false</generateApis>
                <groupId>com.test</groupId>
                <artifactId>test-service</artifactId>
                <modelPackage>test.model</modelPackage>
                <apiPackage>test.api</apiPackage>
                <configOptions>
                    <sourceFolder>src/gen/java/main</sourceFolder>
                    <dateLibrary>java8</dateLibrary>
                    <java8>true</java8>
                </configOptions>
            </configuration>
        </execution>              
    </executions>
</plugin>

I've already tried the typeMappings and importMappings as follow but it had no affect on the generated code:

<typeMappings>DateTime=Instant</typeMappings>
<importMappings>Instant=java.time.Instant</importMappings>
Inweave answered 21/5, 2019 at 11:48 Comment(2)
Did you manage to get this working in the end? I still can't get Instant to work with openApiGenerator and I'm looking for a solution.Michael
The following helped me in my case (generator spring 7.5 + gradle): typeMappings.set(["string+date-time": "Instant"]) importMappings.set([Instant: "java.time.Instant"])Caaba
B
37

Had the same problem but wanted to use LocalDateTime instead of Instant. Adding the following works, at least for entities:

<configuration>
  <typeMappings>
    <typeMapping>OffsetDateTime=LocalDateTime</typeMapping>
  </typeMappings>
  <importMappings>                
    <importMapping>java.time.OffsetDateTime=java.time.LocalDateTime</importMapping>
  </importMappings>
</configuration>

i.e. an import for LocalDateTime is added, and any entity fields in the yaml with type format: date-time are mapped to LocalDateTime.

However, for api parameters, no import was added with those settings. After a while I gave up and instead used fully qualified types so that no import is required. Just change the above typeMapping to:

<typeMapping>OffsetDateTime=java.time.LocalDateTime</typeMapping>

Your generated methods afterwards looked like:

    default ResponseEntity<List<SomeDto>> someMethodGet(
        @ApiParam(value = "") @Valid @RequestParam(value = "changeDateFrom",
            required = false) @org.springframework.format.annotation.DateTimeFormat(
                iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME) java.time.LocalDateTime changeDateFrom,
    {
        return getDelegate().someMethodGet(..., changeDateFrom, ...);
    }

PS1 Make sure you use the most recent version of the plugin.

PS2 I used the delegate pattern.

PS2 I used the spring model.

Bear answered 20/2, 2020 at 12:43 Comment(4)
Just <dateLibrary>java8-localdatetime</dateLibrary> will be enough to make it LocalDateTime (openapi-generator.tech/docs/generators/java). I still can't get it to work with Instant.Michael
@Michael did you have any luck getting it to work with Instant?Selfexamination
No, eventually I gave up, and had to convert it in the java code manually.Michael
For Gradle with Kotlin: typeMappings.set( mapOf( "OffsetDateTime" to "LocalDateTime" ) ) importMappings.set( mapOf( "java.time.OffsetDateTime" to "java.time.LocalDateTime" ) )Milomilon
E
32

just add to the configuration of openapi-generator-maven-plugin

<typeMappings>
     <typeMapping>OffsetDateTime=Instant</typeMapping>
</typeMappings>
<importMappings>                                
     <importMapping>java.time.OffsetDateTime=java.time.Instant</importMapping>
</importMappings>
Expiration answered 18/9, 2019 at 12:39 Comment(0)
R
17

Your changes are overridden by the dateLibrary configuration for the generator. To override date or date-time format types you better disable the dateLibrary by specifying value which is not recognized by the java generators.

Add this to you plugin's <configuration> to achieve this:

  <configOptions>
    <java8>true</java8>
    <dateLibrary>custom</dateLibrary>
  </configOptions>
  <typeMappings>
    <typeMapping>DateTime=Instant</typeMapping>
    <typeMapping>Date=LocalDate</typeMapping>
  </typeMappings>
  <importMappings>
    <importMapping>Instant=java.time.Instant</importMapping>
    <importMapping>LocalDate=java.time.LocalDate</importMapping>
  </importMappings>

You may also want to add <jsr310>true</jsr310> config option, since it is auto enabled when dateLibrary is java8 (but this is used mostly when generating clients as far as I can see).

Ragout answered 11/3, 2020 at 17:3 Comment(0)
C
11

I know the question was about openapi-generator-maven-plugin, but since looking for the same configuration for org.openapi.generator gradle plugin brought me here, I guess this could be useful for someone else:

The equivalent for org.openapi.generator gradle plugin would be:

openApiGenerate {
    // ...
    typeMappings = [
        OffsetDateTime: "Instant"
    ]
    importMappings = [
        "java.time.OffsetDateTime": "java.time.Instant"
    ]
}
Chuck answered 18/11, 2021 at 10:29 Comment(3)
Having a problem with the import not being changed. Any ideas?Stallfeed
Doesn't work for me at all...Drying
Since 5.4.0 of the gradle plugin, the importMappings do not work as one might expect, see: github.com/OpenAPITools/openapi-generator/issues/11506. A workaround would be to remove the importMappings and use OffsetDateTime: "java.time.Instant" in typeMappings.Trappings
B
2

You indeed have to add the mappings as @MaksimYakidovich says, but also change your spec with "format" : "offset-date-time" instead of date-time

Barcot answered 15/11, 2019 at 15:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.