現象
Spring Boot 3対応のついでにorg.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0
にバージョンを上げたところswagger-uiが下記の表示になり正常に動作しなかった。
Unable to render this definition
The provided definition does not specify a valid version field.
Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
解決方法
この現象が発生するのはWebMvcConfigurer
でHttpMessageConverter
をカスタマイズしているためなので、そこにByteArrayHttpMessageConverter
を追加する。
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.clear();
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter());
}
}
公式ドキュメントにも同様の記述がある。
13.79. Why am i getting an error: Swagger UI unable to render definition, when overriding the default spring registered HttpMessageConverter?
When overriding the default spring-boot registered HttpMessageConverter, you should have ByteArrayHttpMessageConverter registered as well to have proper springdoc-openapi support.converters.add(new ByteArrayHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter(jacksonBuilder.build()));
原因
詳細までは調査してないがあるバージョンからjsonをString
ではなくbyte[]
で返すようになったため、ByteArrayHttpMessageConverter
が無いとエラーになるようだ。以下は該当部分 https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/api/OpenApiWebMvcResource.java#L109 の抜粋。
public byte[] openapiJson(HttpServletRequest request, @Value(API_DOCS_URL) String apiDocsUrl, Locale locale)
throws JsonProcessingException {
return super.openapiJson(request, apiDocsUrl, locale);
}