将JSON转换为与Swagger 2.0兼容的JSON Schema草案4。

20

我收到了由REST API生成的JSON文件,其中包含许多属性。

我为这个API创建了一个Swagger 2.0定义,并需要为响应提供相应的模式。

主要问题是:这个JSON文件有很多属性。如果我手动编写模式,将会花费很多时间并且容易出错,而且这不是我需要描述的唯一API。

我知道有一些工具可以将JSON转换为JSON模式,但如果我没有记错的话,Swagger只有$refs指向其他对象定义,因此只有一级,而我发现的工具只产生树形结构的模式。

我的问题是:是否有任何工具可以将JSON(或JSON Schema)转换为适用于Swagger 2.0的模式?

注意:我正在使用YAML,但这不会成为问题,对吗?

例如,我需要什么:

  List of Movements:
    type: "array"
    items:
      $ref: "#/definitions/Movement"
  Movement:
    properties:
      dateKey:
        type: "string"
      movement:
        $ref: "#/definitions/Stock"
    additionalProperties: false
  Stock:
    properties:
      stkUnitQty:
        type: "string"
      stkDateTime:
        type: "string"
      stkUnitType:
        type: "string"
      stkOpKey:
        type: "string"
    additionalProperties: false

对于我的JSON文档:

[
  {
    "dateKey": "20161110",
    "stkLvls": [
      {
        "stkOpKey": "0",
        "stkUnitType": "U",
        "stkDateTime": "20161110T235010.240+0100",
        "stkUnitQty": 30
      }
    ]
  },
  {
    "dateKey": "20161111",
    "stkLvls": [
      {
        "stkOpKey": "0",
        "stkUnitType": "U",
        "stkDateTime": "20161111T231245.087+0100",
        "stkUnitQty": 21
      }
    ]
  }
  ]

但是,http://jsonschema.net/#/ 给我什么:

---
"$schema": http://json-schema.org/draft-04/schema#
type: array
items:
  type: object
  properties:
    dateKey:
      type: string
    stkLvls:
      type: array
      items:
        type: object
        properties:
          stkOpKey:
            type: string
          stkUnitType:
            type: string
          stkDateTime:
            type: string
          stkUnitQty:
            type: integer
        required:
        - stkOpKey
        - stkUnitType
        - stkDateTime
        - stkUnitQty
  required:
  - dateKey
  - stkLvls

虽然我不太了解这方面,但我很好奇,请不要犹豫地深入解释。

提前感谢您的帮助!

3个回答

42

我也需要一个转换工具,偶然发现了这个。到目前为止,它似乎运行得相当不错。它支持JSON和YAML格式。

https://swagger-toolbox.firebaseapp.com/

以下是他们提供的JSON示例:

{
  "id": 1,
  "name": "A green door",
  "price": 12,
  "testBool": false,
  "tags": [
    "home",
    "green"
  ]
}

它生成了这个:

{
    "required": [
        "id",
        "name",
        "price",
        "testBool",
        "tags"
    ],
    "properties": {
        "id": {
            "type": "number"
        },
        "name": {
            "type": "string"
        },
        "price": {
            "type": "number"
        },
        "testBool": {
            "type": "boolean"
        },
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            }
        }
    }
}

Mateuscb,有没有可用的Java库可以将Json Schema转换为Json对象? - Vishwa Pratap
@VishwaPratap 我不确定。我还没有遇到过这种情况。 - mateuscb

5
我知道有一些工具可以将JSON转换为JSON模式,但是如果我没记错的话,Swagger只有对其他对象定义的$refs,因此只有一个级别。你错了。只要它使用支持的子集,Swagger将尊重任何有效的v4 JSON模式。

Schema Object基于JSON Schema规范草案4,并使用预定义的子集。在这个子集的基础上,该规范提供了扩展,以允许更完整的文档。接着列出了JSON模式支持的部分,不支持的部分以及Swagger扩展的部分。


嗨Tom,感谢你的回答。 在https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/uber.yaml中,我可以看到定义标记只有一个级别。当需要使用其他类型时,它们会使用$ref: '#/definitions/Activity'引用其他类型。 但在JSON Schema v4中,这不是强制性的。 有什么解决方案吗? - Cwellan
@tom redgen,是否有可用的Java库可以将Json Schema转换为Json对象? - Vishwa Pratap

4

您可以直接访问https://bikcrum.github.io/Swagger-JSON-Schema-In-YAML_webversion/进行在线转换。

我编写了以下Python脚本以生成保留键顺序在Swagger中使用的YAML格式中的JSON架构。

import json

# input file containing json file
with open('data.json') as f:
    json_data = json.load(f)

# json schema in yaml format
out = open('out.yaml','w')

def gettype(type):
    for i in ['string','boolean','integer']:
        if type in i:
            return i
    return type

def write(string):
    print(string)
    out.write(string+'\n')
    out.flush()

def parser(json_data,indent):
    if type(json_data) is dict:
        write(indent + 'type: object')
        if len(json_data) > 0:
            write(indent + 'properties:')
        for key in json_data:
            write(indent + '  %s:' % key)
            parser(json_data[key], indent+'    ')
    elif type(json_data) is list:
        write(indent + 'type: array')
        write(indent + 'items:')
        if len(json_data) != 0:
            parser(json_data[0], indent+'  ')
        else:
            write(indent + '  type: object')
    else:
        write(indent + 'type: %s' % gettype(type(json_data).__name__))

parser(json_data,'')

更新:如果您想要使用按键排序的YAML(默认情况下),请使用YAML库。
import json
import yaml

# input file containing json file
with open('data.json') as f:
    json_data = json.load(f)

# json schema in yaml format

def gettype(type):
    for i in ['string','boolean','integer']:
        if type in i:
            return i
    return type   

def parser(json_data):
    d = {}
    if type(json_data) is dict:
        d['type'] = 'object'
        for key in json_data:
            d[key] = parser(json_data[key])
        return d
    elif type(json_data) is list:
        d['type'] = 'array'
        if len(json_data) != 0:
            d['items'] = parser(json_data[0])
        else:
            d['items'] = 'object'
        return d
    else:
        d['type'] = gettype(type(json_data).__name__)
        return d

p = parser(json_data)
with open('out.yaml','w') as outfile:
    yaml.dump(p,outfile, default_flow_style=False)

1
我假定你打算使用 indent 而不是 intend。根据我的经验,最好使用整数作为缩进级别,并在最后一刻执行 ' ' * indent(即一个包含两个空格的字符串)。这样,如果您想要四个空格的缩进,只需要更改一个地方即可。(而且,如果您使用 YAML 库,就不必首先跟踪缩进级别)。为什么要导入 pprint?考虑使用 isinstance(var, dict) 代替 type(var) is dict - Anthon
@Authon 感谢您的建议。我已经更新了代码,使用YAML库将JSON转换为YAML,但不会保留键的顺序。如果保留键的顺序很重要,请考虑第一个代码块,其中实现了手动缩进。 - bikram
如果您需要保留键的顺序,请使用ruamel.yaml(我是该软件包的作者):不要使用import yaml,而是使用import ruamel.yaml。不要使用d = {},而是使用d = ruamel.yaml.comments.CommentedMap(),并将dump(...)行更改为两行:yaml = ruamel.yaml.YAML()yaml.dump(p, outfile)。这样应该可以保持排序和块样式。如果您无法使其正常工作,请在此处发布一个问题,并标记为[tag:yaml] [tag:ruamel.yaml],然后我会看到它。 - Anthon
1
那个链接正是我正在寻找的!花费近2000行Swagger代码才找到它。但真希望早些时候就能找到它:( 无论如何,非常感谢你! - user2556381
@bikram 有没有可用的Java库可以将Json Schema转换为Json对象? - Vishwa Pratap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接