Reputation: 113
I am using springdoc-openapi with the latest version (1.3.0). Now I would like sort my tags in the UI by "name" property.
I know about the "springdoc.swagger-ui.tagsSorter" configuration and that I can use a custom sorter function. But I cannot find examples how the function should look like.
I tried the following which does not seem to work:
springdoc.swagger-ui.tagsSorter=(a, b) => a.get("name").localeCompare(b.get("name"))
Upvotes: 11
Views: 22051
Reputation: 3014
The following must be useful. I want to list tags in a custom order, based on the importance and logical grouping of the tags. So I use this OpenApiCustomiser
:
@Configuration
public class SwaggerConfig
{
private static final String[] TAG_FRAGS_IN_ORDER = {
"Important Service",
"Another Service",
"Third Service"
};
// I use tag fragments, in order to avoid to rewrite
// the tags twice
private static int getTagPriority ( Tag tag )
{
for ( int i = 0; i < TAG_FRAGS_IN_ORDER.length; i++ )
{
var frag = TAG_FRAGS_IN_ORDER [ i ];
if ( StringUtils.contains ( tag.getName (), frag ) ) return i;
}
// All the others will go in lexicographical order
return Integer.MAX_VALUE;
}
/**
* The /v1 endpoints
*/
@Bean
public GroupedOpenApi version1Group ()
{
return GroupedOpenApi.builder ()
.group ( "v1" )
.pathsToMatch ( "/v1/**" )
.addOpenApiCustomizer ( oapi ->
{
List<Tag> tags = oapi.getTags ();
// Sort based on priorities
tags.sort (
Comparator.comparingInt ( SwaggerConfig::getTagPriority )
// Last resort for tags of least/same priority: lexicographically
.thenComparing ( Tag::getName, Comparator.naturalOrder () )
);
oapi.setTags ( tags );
})
.build ();
}
/**
* the /test endpoints
*/
@Bean
public GroupedOpenApi testGroup ()
{
...
}
/**
* Common header
*/
@Bean
public OpenAPI apiInfo ()
{
return new OpenAPI ().info (
new Info ()
.title ( "Sample API" )
.description ( "..." )
);
}
}
I use the trick of searching fragments in the tag names, because they have quite long names and I don't want to maintain a list separately. This is an approach that is simpler than other more sophisticated ones.
For instance, an alternative could be defining a custom annotation, eg, @TagOrder
, use it in the controller classed, then search for @Tag and @TagOrder in the classpath and finally sort tags using the two annotations.
Upvotes: 0
Reputation: 76
For sorting schemas , paths and tags in OpenApi.
@Bean
public OpenApiCustomiser openApiCustomiser() {
return openApi -> {
Map<String, Schema> schemas = openApi.getComponents().getSchemas();
openApi.getComponents().setSchemas(new TreeMap<>(schemas));
};
}
@Bean
public OpenApiCustomiser sortPathsAndTagsAlphabetically() {
return openApi -> {
Map<String, PathItem> paths = openApi.getPaths();
Paths sortedPaths = new Paths();
TreeMap<String, PathItem> sortedTree = new TreeMap<String, PathItem>(paths);
Set<Map.Entry<String, PathItem>> pathItems = sortedTree.entrySet();
Map<String, Map.Entry<String, PathItem>> distinctTagMap = new TreeMap<String, Map.Entry<String, PathItem>>();
for ( Map.Entry<String, PathItem> entry:pathItems) {
PathItem pathItem = entry.getValue();
Operation getOp = pathItem.getGet();
if(getOp != null) {
String tag = getOp.getTags().get(0);
if (!distinctTagMap.containsKey(tag)) {
distinctTagMap.put(tag, entry);
}
}
Operation postOp = pathItem.getPost();
if(postOp != null){
String tag1 = postOp.getTags().get(0);
if(!distinctTagMap.containsKey(tag1)){
distinctTagMap.put(tag1,entry);
}
}
Operation putOp = pathItem.getPut();
if(putOp != null) {
String tag2 = putOp.getTags().get(0);
if (!distinctTagMap.containsKey(tag2)) {
distinctTagMap.put(tag2, entry);
}
}
}
LinkedHashMap<String, PathItem> customOrderMap = new LinkedHashMap<String, PathItem>();
for (Map.Entry<String, PathItem> entry: distinctTagMap.values()) {
customOrderMap.put(entry.getKey(), entry.getValue());
}
for(Map.Entry<String, PathItem> entry : sortedTree.entrySet()) {
customOrderMap.putIfAbsent(entry.getKey(), entry.getValue());
}
sortedPaths.putAll(customOrderMap);
openApi.setPaths(sortedPaths);
};
}
Upvotes: 3
Reputation: 1300
With reference from @brianbro's answer, as suggested at https://springdoc.org/faq.html#how-can-i-sort-endpoints-alphabetically
I added
@Tag(name="1. Admin endpoints")
@Tag(name = "2. Everyone's enpoints!")
and below prop to application.yml :
springdoc.swagger-ui.tagsSorter=alpha
And can see them sorted according to numbering on my swagger UI.
Upvotes: 20
Reputation: 4789
By default, you can sort tags alphabetically:
You can have control on the tags order, using OpenApiCustomiser and define your own Comparator:
@Bean
public OpenApiCustomiser sortTagsAlphabetically() {
return openApi -> openApi.setTags(openApi.getTags()
.stream()
.sorted(Comparator.comparing(tag -> StringUtils.stripAccents(tag.getName())))
.collect(Collectors.toList()));
}
Upvotes: 13