提问者:小点点

有没有办法@JsonFormat LocalDate/LocalDateTime字段生成通过openapi-生成器-maven-pluginAPI模型?


我使用openapi生成器maven-plugin在我的spring-boot应用程序中生成API模型

pom. xml:

    <...>
    <dependencies>
        <...>
        <dependency>
            <groupId>org.openapitools</groupId>
            <artifactId>jackson-databind-nullable</artifactId>
            <version>0.2.2</version>
        </dependency>
        <...>
    </dependencies>
    <...>
    <build>
        <plugins>
            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>6.0.1</version>
                <executions>
                    <execution>
                        <id>CLIENT-EVENT</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>
                                ${project.basedir}/src/main/resources/swagger/client_event.json
                            </inputSpec>
                            <generatorName>spring</generatorName>
                            <generateApiDocumentation>false</generateApiDocumentation>
                            <generateApiTests>false</generateApiTests>
                            <generateApis>false</generateApis>
                            <generateSupportingFiles>false</generateSupportingFiles>
                            <generateModelDocumentation>false</generateModelDocumentation>
                            <generateModelTests>false</generateModelTests>
                            <generateModels>true</generateModels>
                            <generateAliasAsModel>false</generateAliasAsModel>
                            <modelPackage>ru.sb.compliance.lcm.dto.client.event</modelPackage>
                            <modelsToGenerate>CreateClientEventRequestData,CreateClientEventResponseData</modelsToGenerate>
                            <configOptions>
                                <delegatePattern>true</delegatePattern>
                                <dateLibrary>java8</dateLibrary>
                            </configOptions>
                            <library>spring-boot</library>
                            <typeMappings>
                                <typeMapping>OffsetDateTime=LocalDateTime</typeMapping>
                            </typeMappings>
                            <importMappings>
                                <importMapping>java.time.OffsetDateTime=java.time.LocalDateTime</importMapping>
                            </importMappings>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <...>

模型中生成的LocalDate/LocalDateTime字段如下所示:

public class CreateClientEventRequestData {

  @JsonProperty("factDt")
  @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
  private LocalDateTime factDt;

  <...>

  public CreateClientEventRequestData factDt(LocalDateTime factDt) {
    this.factDt = factDt;
    return this;
  }

  @Valid 
  @Schema(name = "factDt", description = "дата и время мероприятия", required = false)
  public LocalDateTime getFactDt() {
    return factDt;
  }

  public void setFactDt(LocalDateTime factDt) {
    this.factDt = factDt;
  }

  <...>
}

当我在API中使用这个模型时,factDt像数组一样被序列化:

"data": {
    <...>,
    "factDt":[2022,11,11,20,18,34,71000000],
    <...>
}

我想得到的是

public class CreateClientEventRequestData {

  @JsonProperty("factDt")
  @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy HH:mm:ss")
  private LocalDateTime factDt;

  <...>
}

因此factDt像字符串一样序列化:

"data": {
    <...>,
    "factDt": "11.11.2022 20:18:34",
    <...>
}

如果没有设置@JsonFormat注释,则无法在spring-boot中设置默认序列化模式

我尝试了几个SO建议,但都不奏效,以下是我尝试的:

  • 对LocalDate的注释被序列化为数组
  • https://stackoverflow.com/a/53409514/8990391
  • LocalDateTime以数组格式表示
  • https://stackoverflow.com/a/63698586/8990391(尝试从所有配置中删除@EnableWebMVC)

即使使用这样的最小示例,设置日期格式也不起作用:

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.setTimeZone(TimeZone.getDefault());
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"));

        System.out.println(
                // prints LocalDateTime in default ISO format and not in "dd.MM.yyyy HH:mm:ss" format...
                objectMapper.writeValueAsString(LocalDateTime.now())
        );
    }

所有这些都使得从swagger生成模型而不是在代码中实现它们的想法非常不足……

非常感谢你的帮助


共1个答案

匿名用户

从最后开始,您的最小LocalDateTime序列化示例应该是这样的:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.setTimeZone(TimeZone.getDefault());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

String dateFormat = "dd.MM.yyyy HH:mm:ss";
objectMapper.setDateFormat(new SimpleDateFormat(dateFormat));

SimpleModule module = new SimpleModule();
module.addSerializer(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateFormat)));
objectMapper.registerModule(module);

log.info("serialized local date time = {}", objectMapper.writeValueAsString(LocalDateTime.now()));

这会产生预期的输出:

2022-11-19 23:45:21.794  INFO 24320 --- [           main] c.e.s.SpringWebDemoApplication           : serialized local date time = "19.11.2022 23:45:05"

至于您的主要问题,添加以下bean将在序列化期间完成所需的LocalDateTime格式化工作,而无需对生成的模型类进行任何更改:

private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";

@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
    return builder -> {
        builder.simpleDateFormat(dateTimeFormat);
        builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    };
}

确保您的项目中没有其他Spring自动配置ObjectMapper的配置可能会覆盖这些设置。