Triet Doan
Triet Doan

Reputation: 12085

Prevent Swagger from automatically adding some models

I build a REST interface using Spring Boot framework. Then, I use Swagger version 2.9.2 to generate the documentation. As you can see from the photo below, Swagger automatically detects a lot of models.

Models

However, most of them are redundant. Among them, only the ResponseMessage is necessary, the rest are just standard Java class.

So, my question is: how can I tell Swagger which models to expose?

Here are my Swagger configuration and code snippet of my controller.

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("my.package"))
            .paths(PathSelectors.any())
            .build()
            .apiInfo(API_INFO)
            .useDefaultResponseMessages(false);
}

Controller:

@PostMapping(value = "/import", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> importData(HttpServletRequest request) {

    // processing...

    return ResponseEntity.created(uri)
        .body(new ResponseMessage(HttpStatus.CREATED, "Your data is being processed"));
}

Upvotes: 5

Views: 4640

Answers (5)

Muhammad Hammad Ejaz
Muhammad Hammad Ejaz

Reputation: 51

@Bean
UiConfiguration uiConfig() {
    return UiConfigurationBuilder.builder()
            .defaultModelsExpandDepth(-1)
            .build();
}

This worked for me.

Upvotes: 0

Alisha Raju
Alisha Raju

Reputation: 840

You can use :

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2).select()
            .apis(RequestHandlerSelectors.basePackage("com.package"))
            .paths(PathSelectors.regex("/api.*")).build().apiInfo(apiInfo())
            .ignoredParameterTypes(Timestamp.class);
}

This worked for me. After specifying the class name in ignoredParameterTypes, it was no longer present in swagger ui.

Upvotes: 3

Dheeraj Bathija
Dheeraj Bathija

Reputation: 45

I was able to achieve this by adding genericModuleSubstitutes() in Docket().

Example:

.genericModelSubstitutes(ResponseEntity.class) would substitute ResponseEntity <MyModel> with MyModel.

Reference

Upvotes: 0

nanlan
nanlan

Reputation: 1

Springfox Swagger2 acquire UI data through GET /v2/api-docs, which will mapping to springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation().So you can just create a bean to take place of 'ServiceModelToSwagger2Mapper':

@Primary
@Component
class CustomServiceModelToSwagger2Mapper : ServiceModelToSwagger2MapperImpl() {
    @Autowired
    private lateinit var modelMapper: ModelMapper
    @Autowired
    private lateinit var parameterMapper: ParameterMapper
    @Autowired
    private lateinit var securityMapper: SecurityMapper
    @Autowired
    private lateinit var licenseMapper: LicenseMapper
    @Autowired
    private lateinit var vendorExtensionsMapper: VendorExtensionsMapper

    override fun mapDocumentation(from: Documentation?): Swagger? {
        if (from == null) {
            return null
        }

        val swagger = Swagger()

        swagger.vendorExtensions = vendorExtensionsMapper.mapExtensions(from.vendorExtensions)
        swagger.schemes = mapSchemes(from.schemes)
        swagger.paths = mapApiListings(from.apiListings)
        swagger.host = from.host
// ➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡ here
        swagger.definitions = this.modelsFromApiListings(from.apiListings)
        swagger.securityDefinitions = securityMapper.toSecuritySchemeDefinitions(from.resourceListing)
        val info = fromResourceListingInfo(from)
        if (info != null) {
            swagger.info = mapApiInfo(info)
        }
        swagger.basePath = from.basePath
        swagger.tags = tagSetToTagList(from.tags)
        val list2 = from.consumes
        if (list2 != null) {
            swagger.consumes = ArrayList(list2)
        } else {
            swagger.consumes = null
        }
        val list3 = from.produces
        if (list3 != null) {
            swagger.produces = ArrayList(list3)
        } else {
            swagger.produces = null
        }

        return swagger
    }

    private fun fromResourceListingInfo(documentation: Documentation?): ApiInfo? {
        if (documentation == null) {
            return null
        }
        val resourceListing = documentation.resourceListing ?: return null
        return resourceListing.info ?: return null
    }


    /**
     * @see ModelMapper
     */
    internal fun modelsFromApiListings(apiListings: Multimap<String, ApiListing>): Map<String, Model>? {
        val definitions = newTreeMap<String, springfox.documentation.schema.Model>()
        for (each in apiListings.values()) {
// ➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡ here
            // definitions.putAll(each.models)
            definitions.putAll(each.models.filter {
                it.value.qualifiedType.startsWith("com.cpvsn")
                        && it.value.type.typeBindings.isEmpty    
            })
        }
        return modelMapper.mapModels(definitions)
    }
}

Upvotes: 0

Amith Kumar
Amith Kumar

Reputation: 4884

You can use hidden attribute of @ApiModelProperty to hide any specific property of the model. There is no global setting for it.

Once you have base-package for swagger scan declared, swagger will generate definitions for all components in the package out of box for you. However, with correct use of set of swagger annotations, you can override/customize your swagger documentation.

Please follow these great tutorials (1, 2) to familiarize yourself with most useful annotations & usage.

@Api, @ApiOperation, @ApiResponses, @ApiParam, @ApiIgnore, @ApiModel, @ApiModelProperty etc

Upvotes: 0

Related Questions