Spring自定义CSV消息转换器后Swagger示例仍显示JSON问题求助
问题:Spring自定义HttpMessageConverter后Swagger CSV示例仍显示JSON格式
我已在Spring中实现了AbstractGenericHttpMessageConverter的自定义转换器类:
public class SongConverter extends AbstractGenericHttpMessageConverter<Song> { public SongConverter() { super(new MediaType("text", "csv")); } @Override protected void writeInternal(@NonNull Song song, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { try (var writer = new OutputStreamWriter(outputMessage.getBody())) { new StatefulBeanToCsvBuilder<>(writer).withSeparator(',').build().write(song); } catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException ex) { log.error("Error while writing song to csv", ex); } } @Override public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) { return super.canWrite(clazz, mediaType) && clazz == Song.class; } }
同时配置了WebMvcConfigurer:
@Bean public WebMvcConfigurer configurer() { return new WebMvcConfigurer() { @Override public void configureContentNegotiation(@NonNull ContentNegotiationConfigurer configurer) { configurer.parameterName("mediaType").ignoreAcceptHeader(false) .defaultContentType(MediaType.APPLICATION_JSON) .mediaType("xml", MediaType.APPLICATION_XML) .mediaType("csv", new MediaType("text", "csv")) .mediaType("json", MediaType.APPLICATION_JSON); } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new SongConverter()); //converters.add(new SongsConverter()); } }; }
现在Swagger生成的文档里虽然显示了CSV选项,但对应的示例仍然是JSON格式(添加XML时示例显示正常)。我知道有临时覆盖API默认值的解决方案,但不够稳妥,想问是否遗漏了某些配置?
解决方案
Swagger(OpenAPI)不会自动识别自定义HttpMessageConverter对应的媒体类型示例,必须手动配置该类型的示例生成逻辑,以下是几种可靠的配置方式:
1. 接口级指定CSV示例
在Controller的接口方法上,通过@ApiResponse注解明确指定text/csv类型的响应示例:
@GetMapping(value = "/song", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, "text/csv"}) @ApiResponse(responseCode = "200", description = "成功返回Song数据", content = { @Content(mediaType = "text/csv", schema = @Schema(type = "string"), examples = @ExampleObject(value = "id,name,duration\n1,Hello,180")) }) public Song getSong() { // 业务逻辑实现 }
2. 全局配置CSV示例模板
通过自定义OpenAPI配置和OperationCustomizer,为所有支持text/csv的接口统一添加示例:
@Bean public OpenAPI customOpenAPI() { return new OpenAPI() .components(new Components() .addExamples("csvSongExample", new Example() .summary("CSV格式Song示例") .value("id,name,duration\n1,Hello,180"))) .info(new Info().title("API文档").version("v1")); } @Bean public OperationCustomizer csvExampleCustomizer() { return (operation, handlerMethod) -> { operation.getResponses().values().forEach(response -> { response.getContent().forEach((mediaType, mediaTypeObj) -> { if ("text/csv".equals(mediaType)) { mediaTypeObj.setExample(new ExampleObject().ref("#/components/examples/csvSongExample")); } }); }); return operation; }; }
3. 调整Converter优先级(可选)
确保SongConverter在转换器列表中的优先级足够高,避免被其他通用转换器覆盖。可以修改extendMessageConverters的添加顺序,把自定义转换器放到列表头部:
@Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // 放到列表首位,优先使用自定义转换器 converters.add(0, new SongConverter()); }
注:Song类字段与CSV的映射正确性只影响实际接口返回,和Swagger示例显示无关。
内容的提问来源于stack exchange,提问作者KChas
相关产品推荐
相关产品推荐

