当前位置: 首页 > 知识库问答 >
问题:

Springfox (swagger) - 如何添加动态属性

傅鸿波
2023-03-14

我正在尝试在我的java spring项目中的swagger定义中添加新的属性。我已阅读文档并特别 https://springfox.github.io/springfox/docs/snapshot/#plugins

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Predicates;
import fr.hop.springdatarest.demo.entity.City;
import lombok.extern.java.Log;
import springfox.documentation.builders.ModelPropertyBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.Model;
import springfox.documentation.schema.ModelProperty;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

@Log
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1008)
public class SwaggerDefinitionAddin implements ModelBuilderPlugin {

    @Autowired
    TypeResolver resolver;

    Map<String, ModelProperty> cityAddinMap = new HashMap<String, ModelProperty>();

    @Override
    public boolean supports(DocumentationType delimiter) {
        return DocumentationType.SWAGGER_2.equals(delimiter);
    }

    private Class<?> forClass(ModelContext context) {
        return resolver.resolve(context.getType()).getErasedType();
    }

    @Override
    public void apply(ModelContext modelContext) {

        if(forClass(modelContext) == City.class){

            modelContext.getBuilder().id("TEST").properties(????).build();
        }       
    }

}

例如,我有这个定义:

"definitions": {
    "City": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        },
        "postalCode": {
          "type": "integer",
          "format": "int32"
        }
      }
    },

我想要:

"definitions": {
    "City": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        },
        "postalCode": {
          "type": "integer",
          "format": "int32"
        },
        "meteo": {
          "$ref": "#/definitions/Meteo"
        }
      }
    },

你能帮我在定义中添加meteo属性吗?在本例中,我的目标是以编程方式添加attribute,而不使用注释。

共有1个答案

洪星文
2023-03-14
@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1008)
public class SwaggerDefinitionAddin implements ModelBuilderPlugin {

    @Autowired
    TypeResolver resolver;

    @Autowired 
    TypeNameExtractor typeNameExtractor;

    Map<String, ModelProperty> propertyAddinMap = new HashMap<String, ModelProperty>();



    @Override
    public boolean supports(DocumentationType delimiter) {
        return DocumentationType.SWAGGER_2.equals(delimiter);
    }

    private Class<?> forClass(ModelContext context) {
        return resolver.resolve(context.getType()).getErasedType();
    }

    @Override
    public void apply(ModelContext modelContext) {

        boolean cityScope = false;
        Class<?> modelClass = forClass(modelContext);

        // Detect if it is City modelcontext type instance
        if(modelClass == City.class) {
            cityScope = true;
        }
        // Or an Hateoas resource pointing on City instance
        else if(modelClass.equals(Resource.class)){
            ResolvedType resourceResolveType = resolver.resolve(modelContext.getType()).getTypeBindings().getTypeParameters().get(0);
            if(resourceResolveType.getErasedType().equals(City.class))
                cityScope = true;
        }

        // Add meteo definition in City definition and ResourceCity definition
        if(cityScope){

            ModelPropertyBuilder builder = new ModelPropertyBuilder();
            ModelProperty meteoProperty = builder               
                .name("meteo")
                .type(resolver.resolve(Meteo.class))
                .required(true)
                .isHidden(false)                
                .position(0)                
                .build();

            meteoProperty.updateModelRef(modelRefFactory(modelContext, typeNameExtractor));
            propertyAddinMap.put("meteo",meteoProperty);

            modelContext.getBuilder()           
                .name("City")               
                .properties(propertyAddinMap)
                .build();               
        }       
    }
}

我很难找到springfox生成NPE的原因,在查看源代码后,我发现我们必须设置modelRef:

meteoProperty.updateModelRef(modelRefFactory(modelContext, typeNameExtractor));

希望帮助别人:)

 类似资料:
  • 预期结果:用循环去写,现在是写死的,当长度是2的时候是 obj= _tableArray[nodeList[0]].children[nodeList[1]]

  • 我正在使用为应用程序公开的restapi生成Swagger-API文档。 我需要手动添加API的文档,从技术上讲,该API没有REST控制器。如何手动添加到Swagger API文档中?我想从代码开始做一次。

  • 问题内容: 目标是创建一个行为类似db结果集的模拟类。 因此,例如,如果数据库查询使用表达式返回,那么我想看看: 刚开始我以为我可以这样做: 但返回一个属性对象。 用替换该行根本没有用。 那么在运行时创建实例属性的正确方法是什么? 问题答案: 我想我应该扩大这个答案,因为我年纪大一些并且比较聪明,并且知道发生了什么事。迟到总比不到好。 你可以动态地向类添加属性。但这很重要:你必须将其添加到类中。

  • 我想在Angular 7中动态添加div属性。 我尝试了这个: 我有一个错误: 未捕获的错误:模板分析错误:无法绑定到“code ”,因为它不是“div”的已知属性。(" *ngFor="let e of etats。_ embedded . Etats " style = " background:{ { e . codecouleur } }!重要;“[错误-

  • 而在帖子上,我应该看到的只是: 尝试添加:@apimodelproperty(readonly=true)。但那没用。

  • 问题内容: 嗨:在我们的应用程序中,我们已经从数据库中检索了一些数据,例如,表中包含以下字段:id,名称,年龄,地址,电子邮件。 然后,我们将根据客户提供一些这些属性。 如果客户需要ID,名称,我们将获得ID名称;如果客户需要ID,名称,年龄,则将获得ID,名称,年龄。 现在,我们想创建一个包装这些属性的类。但是,我们不知道确切要求哪个字段。 我可以在这里用Class替换地图吗? 问题答案: 如果