序列化OpenAPI示例时丢失请求类型信息的问题排查
问题:SpringDoc中包装请求实例进Example后丢失Jackson多态@type标识
我定义了多态请求类型CreateRequest,包含CreateFooRequest和CreateBarRequest两个子类,通过自定义SimpleNameIdResolver实现Jackson多态类型识别。使用springdoc(1.8.0版本)编写OpenAPI示例时,将请求实例包装进Example对象后序列化,结果丢失@type类型标识字段;但直接序列化请求实例,或序列化请求中同样采用多态实现的Rule字段数组时,@type标识可正常保留。为何包装进Example后会丢失类型信息?
原因分析
核心问题出在SpringDoc处理Example对象的序列化逻辑上:
- 直接序列化请求实例或
Rule数组时,用的是你项目中配置了自定义SimpleNameIdResolver的ObjectMapper,多态类型标识@type自然会正常输出。 - 但将对象包装进
Example后,SpringDoc 1.8.0内部在处理示例内容时,并没有复用你配置好的ObjectMapper,而是使用了自身默认的序列化机制,这套机制没有加载你的多态类型解析器配置,导致@type字段丢失。 - 另外该版本本身存在Jackson多态类型处理的兼容性缺陷,在包装
Example对象时,没有正确触发多态序列化的逻辑分支。
解决方案
1. 手动序列化后再传入Example
绕过SpringDoc的默认序列化,用你自己的ObjectMapper先把请求实例转成JSON字符串,再设置到Example对象中:
// 使用项目中配置好的ObjectMapper String requestJson = objectMapper.writeValueAsString(createFooRequest); Example example = new Example().value(requestJson);
2. 强制SpringDoc使用项目的ObjectMapper
通过自定义OpenApiCustomiser,让SpringDoc在处理示例时复用你的ObjectMapper配置:
@Bean public OpenApiCustomiser openApiCustomiser(ObjectMapper objectMapper) { return openApi -> { openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> operation.getRequestBody().getContent().values().forEach(mediaType -> mediaType.getExamples().values().forEach(example -> { if (example.getValue() instanceof Object) { try { String jsonStr = objectMapper.writeValueAsString(example.getValue()); example.setValue(jsonStr); } catch (JsonProcessingException e) { // 按需处理序列化异常 } } }) ) ) ); }; }
3. 升级SpringDoc版本
SpringDoc后续版本(如1.9.x及以上)修复了多态类型处理的相关问题,升级后可能无需额外配置就能正常保留@type标识。
内容的提问来源于stack exchange,提问作者Ben R.
相关产品推荐
相关产品推荐

