如何从Swagger API声明生成JSON模式

w7t8yxp5  于 2022-11-06  发布在  其他
关注(0)|答案(7)|浏览(607)

我有使用Swagger v 1.2的服务的Swagger API声明。
我最初对Swagger的感觉是,它非常接近JSON Schema(Draft 3和最近的Draft 4),为请求和响应对象生成JSON Schema应该相对容易。
然而,虽然Swagger的一部分重用了JSON Schema结构,但事实证明它只使用了一个特性子集,而且它还在模型中引入了自己的继承(使用subTypesdiscriminator)。
问:是否有任何现有的项目或代码可以从Swagger API声明生成可用的JSON模式
最好是JSON模式草案4和使用Python(但我会很高兴找到任何东西)。

ugmeyewa

ugmeyewa1#

在使用Swagger指定REST API并在相关测试套件中重用它的过程中,经过了较长时间的斗争,我将与它分享我自己的经验(回答我自己的问题)。

Swagger仅支持JSON模式草案4的子集

Swagger 1.2和2.0规范规定,它只支持JSON Schema Draft 4的子集(此处为s.)。这意味着:

  • 我们不能相信每个有效的JSON模式都能被Swagger完全支持。
  • 考虑到XML,Swagger只支持JSON模式草案4提供的JSON结构子集的规范表示。

换句话说就是:

  • Swagger(1.2和2.0)不支持使用许多JSON结构,这些结构在JSON Schema Draft 4中是有效的(这同样适用于Draft 3)。
  • Swagger不支持通用的XML数据结构,只允许非常受限的结构。

在实践中,您不能从JSON或XML中设计数据开始,使用Swagger时,您必须从Swagger开始并以其结束。

获取JSON模式在理论上是可行的,但并不容易

我已经花了一些时间编写了一个库,它将采用Swagger API规范并创建JSON Schema Draft 4。我放弃的原因有两个:

  • 一点也不容易
  • 我失望地发现,我只能使用JSON模式提供的部分内容。我们已经提出了一些JSON有效负载,不得不开始修改它,以适应Swagger规范框架所允许的内容。

除了有非常好看的UI来显示和测试API(是的,每个人都同意,它在视觉上非常令人愉快),我发现它很奇怪,规范框架不允许我们使用我们想要的,而是给我们的设计增加了意想不到的限制。

如果您想要完整的JSON或XML模式支持,请使用RAML

通过研究其他API规范框架,我发现了RAML。由于它是通过支持任何JSON Schema Draft 3/4或W3C XML Schema 1. 0数据结构从头开始构建的,因此体验非常棒-设计了有效负载的结构,我能够非常快速地编写API规范,并且根据定义的模式对真实的请求和响应进行验证非常容易,因为模式是规范的基本组成部分而无需对它们添加任何限制。
RAML当时是0.8版本(1.0版本还没有发布)。

纠正问题会带来真实的的解决方案

好的问题是解决问题的一半。我的问题是错误的,因为它没有达到我的真实的期望。更正的问题是:

要使用什么规范框架和技术来指定使用任意JSON Schema Draft 4或W3C XML Schema 1.0定义的有效负载的REST API。

我对这样一个问题的回答是:
1.在JSON Schema Draft 4或W3C XML Schema中设计有效负载
1.通过RAML(目前为v0.8)描述REST API。
也许还有其他的规范框架可以使用,但是Swagger(v1.2和v2.0都不是)绝对不是这样的。除了提供了很多特性(代码生成,非常漂亮的API文档等等),它只是没有提供上面提到的更新问题的解决方案。

9rbhqvlz

9rbhqvlz2#

有一个名为openapi2jsonschema的python工具可以做同样的事情。你可以简单地使用pip安装它。
openapi2的自述文件给出了最简单的使用方法:

openapi2jsonschema https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json

希望这对你有帮助。

f87krz0w

f87krz0w3#

我刚刚写了一个工具pyswagger似乎适合你的需要。
它加载Swagger API声明,能够将python对象转换为Swagger原语/从Swagger原语转换为python对象**。还提供了一组客户端实现(包括requests&tornado.httpclient.AsyncHTTPClient),能够直接向支持Swagger的服务发出请求。
这个工具解决了我在Python中使用Swagger时遇到的第一个问题,现在仍然很新。欢迎提出任何建议。

cbeh67ev

cbeh67ev4#

我曾经这样做过:
yaml -〉原-〉jsonschema
我使用openapi2proto从Swagger yaml生成proto文件,然后使用protoc-gen-jsonschema从该文件生成JSONSchemas。获得类型化的JSONSchema已经足够了,但是proto 3不支持“必需的”类型,所以您错过了这一点。

hi3rlvi2

hi3rlvi25#

我编写了一个递归函数,用于从Swagger定义创建json模式。
例如,考虑swagger规范petstore-minimal
定义Pet被转换为下面的json-schema

{
  "description": null,
  "type": "object",
  "properties": {
    "name": {
      "description": null,
      "type": "string"
    },
    "id": {
      "format": "int64",
      "description": null,
      "type": "integer"
    },
    "tag": {
      "description": null,
      "type": "string"
    }
  }
}

当然,这是一个非常小的json模式,但是使用我编写的函数可以实现更多的功能。

<dependency>
        <groupId>io.swagger.parser.v3</groupId>
        <artifactId>swagger-parser</artifactId>
        <version>2.1.2</version>
    </dependency>

为了创建json模式,我使用了下面的maven依赖项

<dependency>
        <groupId>net.minidev</groupId>
        <artifactId>json-smart</artifactId>
        <version>2.4.7</version>
    </dependency>

现在到了编码部分,输入是swagger规范的位置,也是我们需要转换为json模式的定义名称。

public static void main(String[] args) {
    String jsonSchema = SwaggerUtil.generateJsonSchemaFromSwaggerSpec("path to swagger spec", "Pet");
    System.out.println(jsonSchema);
}

现在,我们需要处理作为输入传递的swagger定义,并递归地处理定义的属性

public static String generateJsonSchemaFromSwaggerSpec(String swaggerPath, String fieldName){

    Swagger swagger = new SwaggerParser().read(swaggerPath);
    Map<String, Model> definitions = swagger.getDefinitions();
    Model schemaGenerationDefinition = definitions.get(fieldName);
    Map<String, Property> propertyMap = schemaGenerationDefinition.getProperties();

    Map<String, JsonProperty> customJsonPropertyMap = new HashMap<>();
    propertyMap.forEach((propertyName, property) -> {
        JsonProperty jsonProperty = processSwaggerProperties(propertyName, property, definitions);
        customJsonPropertyMap.put(propertyName, jsonProperty);
    });
    JsonObjectProperty objectProperty = new JsonObjectProperty(customJsonPropertyMap, schemaGenerationDefinition.getDescription());
    JSONObject generatedObject = objectProperty.toJsonObject();
    String jsonSchema = generatedObject.toJSONString();
    return jsonSchema;
}

private static JsonProperty processReference(String referenceName, String type, Map<String, Model> definitions){

    Model model = definitions.get(referenceName);
    Map<String, Property> propertyMap = model.getProperties();
    Map<String, JsonProperty> jsonPropertyMap = new HashMap<>();
    propertyMap.forEach((propertyName, property) -> {
        JsonProperty jsonProperty = processSwaggerProperties(propertyName, property, definitions);
        jsonPropertyMap.put(propertyName, jsonProperty);
    });
    if (type.equalsIgnoreCase("array")){
        JsonArrayProperty jsonProperty = new JsonArrayProperty(model.getDescription());
        jsonProperty.loadPropertiesFromMap(jsonPropertyMap);
        return jsonProperty;
    }else{
        JsonObjectProperty objectProperty = new JsonObjectProperty(jsonPropertyMap, model.getDescription());
        return objectProperty;
    }
}

private static JsonProperty processSwaggerProperties(String propertyName, Property property, Map<String, Model> propertyDefinitions){
    String definitionRefPath = "";
    String type = "";
    JsonProperty jsonProperty = null;
    if (property.getType().equalsIgnoreCase("ref")){
        definitionRefPath = ((RefProperty) property).getOriginalRef();
        type = "object";
    }else if (property.getType().equalsIgnoreCase("array")){
        type = "array";
        Property childProperty = ((ArrayProperty) property).getItems();
        if (childProperty instanceof RefProperty){
            RefProperty refProperty = (RefProperty) ((ArrayProperty) property).getItems();
            definitionRefPath = refProperty.getOriginalRef();
        }else{
            JsonArrayProperty arrayProperty = new JsonArrayProperty(property.getDescription());
            arrayProperty.loadChildProperty(childProperty);
            return arrayProperty;
        }
    }else{
        jsonProperty = PropertyFactory.createJsonProperty(property);
        return jsonProperty;
    }
    String[] splitResult = definitionRefPath.split("/");
    if (splitResult.length == 3) {
        String propertyPath = splitResult[2];
        System.out.println(propertyPath);
        jsonProperty = processReference(propertyPath, type, propertyDefinitions);
    }
    return jsonProperty;
}

因此,为了创建json模式,我创建了自己的自定义json模式类。这是针对每种json模式数据类型的。

public class PropertyFactory {

    public static JsonProperty createJsonProperty(Property property){
        JsonProperty jsonProperty = null;
        switch (property.getType()){
            case "number":
                jsonProperty = new JsonNumberProperty(property.getFormat(), property.getDescription());
                break;
            case "string":
                jsonProperty = new JsonStringProperty(property.getDescription());
                break;
            case "boolean":
                jsonProperty = new JsonBooleanProperty(property.getDescription());
                break;
            case "integer":
                jsonProperty = new JsonIntegerProperty(property.getFormat(), property.getDescription());
                if (property instanceof IntegerProperty){
                    IntegerProperty integerProperty = (IntegerProperty) property;
                    if (integerProperty.getMinimum() != null)
                        ((JsonIntegerProperty) jsonProperty).setMinimum(integerProperty.getMinimum());
                    if (integerProperty.getMaximum() != null)
                        ((JsonIntegerProperty) jsonProperty).setMaximum(integerProperty.getMaximum());
                }else if (property instanceof LongProperty){
                    LongProperty longProperty = (LongProperty) property;
                    if (longProperty.getMinimum() != null)
                        ((JsonIntegerProperty) jsonProperty).setMinimum(longProperty.getMinimum());
                    if (longProperty.getMaximum() != null)
                        ((JsonIntegerProperty) jsonProperty).setMaximum(longProperty.getMaximum());
                }
                break;
            default:
                System.out.println("Unhandled type");
        }

        return jsonProperty;
    }
}

下面是我为每种json数据类型创建的抽象
第一个问题

注意事项

这是我根据自己的需要所做的自定义实现,如果您遇到任何其他数据类型,只需通过扩展JsonProperty类并提供toJsonObject实现来创建该类型。
快乐编码

e0bqpujr

e0bqpujr6#

使用Swagger UI进行文档化,突出显示的链接返回您的API模式的json对象:

klr1opcd

klr1opcd7#

将OpenApi安装到Jsonschema提取器:
打开终端-执行以下命令

sudo yum install python-pip
pip install openapi2jsonschema
  • 将openApi yaml文件下载到文件夹
  • cd到下载的文件夹,然后运行此命令
openapi2jsonschema --strict <openapi yaml filename>

相关问题