Swagger/OpenApi 似乎不理解我的 LocalTime 类型的 DTO 字段,为请求正文创建 JSON 而不是字符串

问题描述 投票:0回答:1

Swagger/OpenAPI v3 不尊重问题
LocalTime
Spring Boot DTO 中的数据类型

环境:

  • Spring Boot: 3.3.2
  • Java: 17(亚马逊 Corretto)
  • PostgreSQL: 15.3
  • Swagger/OpenAPI: Springdoc OpenAPI v3 (2.6.0)
  • 杰克逊:使用默认的杰克逊映射器

问题描述:

我正在开发一个 Spring Boot 应用程序,其中有一个 DTO,其中包含

LocalTime
entryTime
字段。尽管使用
@JsonFormat
指定时间格式,Swagger(通过 Springdoc OpenAPI)仍将
entryTime
显示为带有
hour
minute
second
nano
字段的 JSON 对象。当我尝试通过 swagger UI 与 API 交互时,这会导致错误。具体来说,我收到此错误:

发生错误:JSON 解析错误:无法从对象值(令牌

java.time.LocalTime
)反序列化类型
JsonToken.START_OBJECT
的值

有问题的 DTO 属性字段:

    @NotNull(message = "Entry time is required")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
    private LocalTime entryTime;

预期的 API 请求正文:

{
  "weight": 0,
  "ketoneLevel": 100,
  "entryDate": "2024-10-19",
  "entryTime": "00:00:00"
}

Swagger/OpenAPI 显示的内容:

尽管有上面的注释和配置,Swagger 显示

entryTime
字段如下:

{
  "weight": 0,
  "ketoneLevel": 100,
  "entryDate": "2024-10-19",
  "entryTime": {
    "hour": 0,
    "minute": 0,
    "second": 0,
    "nano": 0
  }
}

我尝试过的:

  1. 添加

    @JsonFormat
    注释:

    • 我在
      @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
      字段上使用了
      LocalTime
      ,希望 Swagger 将其识别为字符串。
  2. 使用

    @Schema
    注释:

    • 尝试添加
      @Schema(type = "string", pattern = "HH:mm:ss")
      为 OpenAPI 提供额外的元数据。这并没有改变 Swagger 显示的请求主体结构。
  3. 调整 Jackson 配置:

    • 已验证 Jackson 是否正确地将
      LocalTime
      序列化为响应中的字符串,但这似乎并不影响 Swagger 生成请求架构的方式。
  4. 使用不同的时间表示进行测试:

    • 当使用
      "entryTime": "2024-10-19T00:00:00.000"
      发送请求时,它成功解析时间并将其按预期存储在数据库中:
      select * from fitness_entry;
      
      entry_id | entry_date | entry_time | ketone_level | weight | created_at           | member_id
      ---------+------------+------------+--------------+--------+----------------------+-----------
      1        | 2024-10-19 | 00:00:00   | 99.00        | 0.00   | 2024-10-19 00:00:00  | 1
      

fitness_entry
的数据库架构:

\d fitness_entry;
                                              Table "public.fitness_entry"
    Column    |              Type              | Collation | Nullable |                     Default                     
--------------+--------------------------------+-----------+----------+-------------------------------------------------
 entry_id     | bigint                         |           | not null | nextval('fitness_entry_entry_id_seq'::regclass)
 entry_date   | date                           |           | not null | 
 entry_time   | time(6) without time zone      |           | not null | 
 ketone_level | numeric(4,2)                   |           |          | 
 weight       | numeric(5,2)                   |           | not null | 
 created_at   | timestamp(6) without time zone |           | not null | CURRENT_TIMESTAMP
 member_id    | bigint                         |           | not null | 

当前解决方法:

使用

entryTime
作为字符串(例如
"2024-10-19T00:00:00.000"
)发送请求确实有效,并且该值已正确存储在数据库中。然而,这并没有正确反映在 Swagger/OpenAPI 生成的 API 文档中,导致用户感到困惑。

预期结果:

我希望 Swagger/OpenAPI 将

entryTime
字段识别为请求正文中的简单
string
类型,而不是具有
hour
minute
second
nano
字段的对象。

问题:

如何让 Swagger/OpenAPI v3 将

LocalTime
字段正确解释为请求正文中的
string
?我是否缺少特定的注释或配置来实现此目的?

任何指导或建议将不胜感激!干杯!

spring-boot serialization jackson swagger
1个回答
0
投票

 spring:
  jackson:
    serialization:
      write-dates-as-timestamps: false







@NotNull(message = "Entry time is required")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
@Schema(type = "string", pattern = "HH:mm:ss", example = "12:00:00")
private LocalTime entryTime;






@Configuration
public class SpringDocConfig {

    @Bean
    public OpenApiCustomiser customOpenApi() {
        return openApi -> openApi.getComponents()
                .addSchemas("LocalTime", new Schema<>().type("string").example("12:00:00"));
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.