swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.93k stars 6.03k forks source link

java8 / java8-localdatetime options are ignored #7730

Open jbequinn opened 6 years ago

jbequinn commented 6 years ago
Description

Hi. I'm using the command line codegen to generate a Java model using the Java 8 options for dates/times, but I can see that the generated Java classes have references to Joda instead, like this:

@SerializedName("timeOfDayFrom")
private org.joda.time.* timeOfDayFrom = null;

I've also noticed this in the output:

[main] INFO io.swagger.codegen.DefaultGenerator - Model LocalTime not imported due to import mapping
Swagger-codegen version

I'm using the current master branch, which is 2.4.0-SNAPSHOT.

Swagger declaration file content or url

I'm using a JSON declaration generated by camel-rest-swagger. The relevant part is this one:

...

"timeOfDayFrom" : {
  "description" : "Minimum time of day (inclusive) to include in search results. Null means no minimum. ISO 8601 format, e.g.: 12:34:56",
  "$ref" : "#/definitions/LocalTime"
},

...

"LocalTime" : {
  "type" : "object",
  "properties" : {
    "hour" : {
      "type" : "integer",
      "format" : "int32"
    },
    "minute" : {
      "type" : "integer",
      "format" : "int32"
    },
    "second" : {
      "type" : "integer",
      "format" : "int32"
    },
    "nano" : {
      "type" : "integer",
      "format" : "int32"
    }
  }
},

The original model is also Java, and the variable looks like this:

@ApiModelProperty("Minimum time of day (inclusive) to include in search results. Null means no minimum. ISO 8601 format, e.g.: 12:34:56")
private LocalTime timeOfDayFrom;
Command line used for generation
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i http://10.17.1.65:8102/api/doc -l java -o /tmp/java-client -DdateLibrary=java8
Related issues/PRs

This issue seems to be related, but it's closed already: https://github.com/swagger-api/swagger-codegen/issues/7177

Suggest a fix/enhancement

I've found out that if I remove these lines from DefaultCodegen.java

importMapping.put("DateTime", "org.joda.time.*");
importMapping.put("LocalDateTime", "org.joda.time.*");
importMapping.put("LocalDate", "org.joda.time.*");
importMapping.put("LocalTime", "org.joda.time.*");

Then the Java model is created correctly:

@SerializedName("timeOfDayFrom")
private LocalTime timeOfDayFrom = null;

Is it really a bug, or am I doing something wrong? Thank you very much.

jmini commented 6 years ago

You have defined a definition called LocalTime. I guess a class io.swagger.client.model.LocalTime was generated ?

It seems that swagger checks that class name is not imported if it is in conflict with other imports, like the joda-time objects.

I guess that if you rename you definition to something else like MyLocalTime, then it will work.

...

"timeOfDayFrom" : {
  "description" : "Minimum time of day (inclusive) to include in search results. Null means no minimum. ISO 8601 format, e.g.: 12:34:56",
  "$ref" : "#/definitions/MyLocalTime"
},

...

"MyLocalTime" : {
  "type" : "object",
  ...
},

An other idea could be to use themodelNamePrefix option to prefix all your Model classes with a custom prefix. This way your object will be: io.swagger.client.model.MyPrefixLocalDateTime.

I did not test it.

jbequinn commented 6 years ago

Thanks for the response.

Yes, a io.swagger.client.model.LocalTime was generated after all, and its contents mimic java.time.LocalTime. Would it be possible that this io.swagger.client.model.LocalTime is not generated, but java.time.LocalTime is used instead?

Also please notice that I don't have much control of the JSON definition, because it's generated by camel-rest-swagger.

jmini commented 6 years ago

I have no idea if it is possible to replace a custom definition with a java type. How can the generator know that io.swagger.client.model.LocalTime is the same as io.swagger.client.model.LocalTime and your marshaller needs to know how to do the conversion.

I would use a custom prefix for all your Model classes (modelNamePrefix). This way you will not have the conflict.

Maybe someone has a better idea.

klowtherjr007 commented 5 years ago

This isn't a problem of a custom class per se. He didn't define a custom class, but is using the Java 8 LocalTime class. It appears to be a class name conflict between the Joda packages and the Java Time package. A LocalTime class exists in both and currently Swagger Codegen defaults to generating using the Joda class rather than the Java 8 class. It doesn't matter if the user specifies java8 or java8-localdatetime as a date library config option in the plug-in configuration.

Update: The way to fix this via configuration is to add an import mapping entry to the plug-in configuration as below:

<importMappings>LocalTime=java.time.LocalTime</importMappings>

It is because the default config (as noted above by @bquintanjm) is predisposed to Joda. This overrides that default.

selimok commented 1 year ago

Thanks @klowtherjr007, the workaround works. But I should have done some complementary changes so that both LocalTime and LocalDate are mapped correctly >>

        <plugin>
            <groupId>io.swagger.codegen.v3</groupId>
            <artifactId>swagger-codegen-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        ...
                        <importMappings>
                            <importMapping>LocalTime=java.time.LocalTime</importMapping>
                            <importMapping>LocalDate=java.time.LocalDate</importMapping>
                        </importMappings>
                        ....
                    </configuration>
                </execution>
            </executions>
        </plugin>