一个小问题:Swagger 不显示 VO,Swagger 泛型丢失

真正的原因是"SpringDoc 的坑"

⚠️ 结论

SpringDoc 在"静态工厂方法 + 嵌套泛型返回值"场景下,
有时无法正确推断 T 的真实类型

也就是说:

java 复制代码
public R<List<FriendVO>> listFriends() {
    return R.ok(friends);
}

Java 编译期是没问题的
运行期业务也是完全 OK 的

❌ 但 SpringDoc 在生成 OpenAPI Schema 时,推断失败

所以它只生成了:

复制代码
R
 └─ data: object

不会展开 FriendVO


为什么会这样?

  • Java 泛型 运行期会擦除

  • SpringDoc 主要靠:

    • 方法返回签名(返回类型)
    • 注解
    • 反射
  • 静态泛型工厂方法(R.ok(T data))是关键触发点

bash 复制代码
 Java 中完整方法签名 = 方法名 + 参数列表(类型、数量、顺序)
 而方法返回签名专指方法的返回值类型(注意:仅包含类型,不包含返回值名称 / 变量)

SpringDoc 有时候能推断

有时候推断不了(尤其是 R<List<VO>> 这种双层泛型)

👉 这是 SpringDoc 2.x 的已知行为


✅ 解决方案一(最推荐 )

👉 在 Controller 方法上 显式声明 Response Schema

java 复制代码
@Operation(
    summary = "查询我的好友列表",
    description = "传入当前登录用户ID,查询已成功建立好友关系的全部好友列表"
)
@ApiResponse(
    responseCode = "200",
    description = "成功",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = FriendVO.class)
    )
)
@GetMapping("/list")
public R<List<FriendVO>> listFriends(
        @NotNull @Min(1) @RequestParam Long userid) {
    return R.ok(friendService.getFriendList(userid));
}

🔥 这一行是"核按钮":

java 复制代码
@Schema(implementation = FriendVO.class)

📌 含义:
"别猜了,我明确告诉你 data 里装的是 FriendVO"


✅ 解决方案二(更优雅,适合多个接口)

R.data 加一个 @Schema 提示

你已经写了:

java 复制代码
@Schema(description = "业务数据载体,成功时返回具体业务数据,失败时为null,泛型适配任意类型数据")
private T data;

👉 但 SpringDoc 仍然不知道 T 是什么

可以加一个 泛型兜底(实战常用):

java 复制代码
@Schema(
    description = "业务数据",
    oneOf = { FriendVO.class }
)
private T data;

⚠️ 不过这个方式 适合单一业务域

如果 R 是全局通用,方案一更干净


✅ 解决方案三(调试 / 验证用,非最终)

加一个"直返 VO 的接口":

java 复制代码
@GetMapping("/_debug/friend-vo")
public FriendVO debugFriendVO() {
    return new FriendVO();
}

如果这个 能在 Schemas 里看到 FriendVO

👉 那就 100% 证明不是 VO / Lombok / 注解问题

相关推荐
xiaoqiMikko8 分钟前
你升的是 jackson-databind,中招的是 jackson-core:一个超长 JSON key 就能吃掉 200MB 堆
java·安全
不正经的码狗12 分钟前
Eclipse汉化(快速,推荐)
java·eclipse
极客互动API14 分钟前
极客互动-企业微信基于外部API接口实现AI客服自动接管外部联系人消息收发
java·微信·企业微信·ai编程·rpa
Sam_Deep_Thinking16 分钟前
关于java final关键字的可见性
java·后端·面试·程序员
tryxr17 分钟前
矩阵的几种基础变换
java·数据结构·算法·矩阵
写后端的胖头鱼18 分钟前
如何区分IO/CPU 密集型,线程池核心参数怎么设置
java·线程池·多线程·io密集·cpu密集
JAVA面经实录91741 分钟前
IDEA 开发知识
java·intellij-idea·idea
于樱花森上飞舞1 小时前
【Redis】哨兵详解
java·开发语言·数据库·redis
2601_953824611 小时前
基于SSM的水果超市管理系统
java·tomcat·maven
guo_wen_qiang1 小时前
springboot如何自定义一个启动器starter
java·spring boot·intellij-idea