Feature Description
Duplicate class names are not resolved by the library (see #5016).
One special case of name clashes have to do with nested classes.
We ran into schema-name collisions when two top-level models each define a nested class with the same simple name.
Today the behavior seems to be effectively binary:
- default naming uses the simple class name, for example SiteStop
- fully qualified naming uses the package + class name, for example com.example.TripExport.SiteStop
The first option causes collisions for nested types with the same simple name.
The second option avoids collisions, but it exposes package names in the public OpenAPI schema, which is often more verbose than desired.
This feature is a request to include the outer name to prevent name clashes.
For example:
TripExport.SiteStop
PublishedTrip.SiteStop
Use Case
The issue would prevent name clash in this case:
package com.example.demo;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DemoController {
@GetMapping("/trip")
public TripExport trip() {
return null;
}
@GetMapping("/published-trip")
public PublishedTrip publishedTrip() {
return null;
}
}
class TripExport {
public List<SiteStop> siteStops;
static class SiteStop {
public String stopId;
}
}
class PublishedTrip {
public List<SiteStop> siteStops;
static class SiteStop {
public String stopId;
}
}
Suggested Solution (optional)
The problem can we resolved (or worked around) by implementing implementing a different TypeNameResolver and registering it in a ModelResolver.
@Bean
public static ModelResolver createModelResolver(ObjectMapper objectMapper) {
return new ModelResolver(objectMapper, new NestedTypeNameResolver());
}
static final class NestedTypeNameResolver extends TypeNameResolver {
@Override
protected String getNameOfClass(Class<?> cls) {
if (cls.getEnclosingClass() == null) {
return cls.getSimpleName();
}
Deque<String> names = new ArrayDeque<>();
for (Class<?> current = cls; current != null; current = current.getEnclosingClass()) {
names.push(current.getSimpleName());
}
return String.join(".", names);
}
}
Alternatives Considered
The fqn toggle also prevens the collision but includes the full package name in the schema, which was not desired in our case.
Feature Description
Duplicate class names are not resolved by the library (see #5016).
One special case of name clashes have to do with nested classes.
We ran into schema-name collisions when two top-level models each define a nested class with the same simple name.
Today the behavior seems to be effectively binary:
The first option causes collisions for nested types with the same simple name.
The second option avoids collisions, but it exposes package names in the public OpenAPI schema, which is often more verbose than desired.
This feature is a request to include the outer name to prevent name clashes.
For example:
TripExport.SiteStop
PublishedTrip.SiteStop
Use Case
The issue would prevent name clash in this case:
Suggested Solution (optional)
The problem can we resolved (or worked around) by implementing implementing a different TypeNameResolver and registering it in a ModelResolver.
Alternatives Considered
The fqn toggle also prevens the collision but includes the full package name in the schema, which was not desired in our case.