39

我需要使用 Swagger 记录一个 API,该 API 将对象映射用作输入和输出,并由字符串键索引。

例子:

{
    "a_property": {
        "foo": {
            "property_1": "a string 1",
            "property_2": "a string 2"
        },
        "bar": {
            "property_1": "a string 3",
            "property_2": "a string 4"
        }
    }
}

"foo" 和 "bar" 可以是任何字符串键,但它们在键集中应该是唯一的。

我知道,使用 Swagger,我可以定义一个对象数组,但这提供了不同的 API,因为我们将拥有如下内容:

{
    "a_property": [
        {
            "key": "foo"
            "property_1": "a string 1",
            "property_2": "a string 2"
        },
        {
            "key": "bar"
            "property_1": "a string 3",
            "property_2": "a string 4"
        }
    ]
}

我已阅读“开放 API 规范”-“添加对地图数据类型 #38 的支持”页面。据我了解,它建议使用附加属性,但它似乎无法满足我的需求(或者它不适用于我使用的 Swagger UI 2.1.4)。我错过了什么?

到目前为止,我已经找到了以下解决方法(在 Swagger JSON 中):

a_property: {
    description: "This is a map that can contain several objects indexed by different keys.",
    type: object,
    properties: {
        key: {
            description: "map item",
            type: "object",
            properties: {
                property_1: {
                    description: "first property",
                    type: string
                },
                property_2: {
                    description: "second property",
                    type: string
                }
            }
        }
    }
}

这几乎可以完成这项工作,但读者必须了解“key”可以是任何字符串,并且可以重复多次。

有没有更好的方法来实现我所需要的?

4

4 回答 4

52

使用additionalProperties是使用 OpenAPI (fka. Swagger) 规范描述哈希图的正确方法,但 Swagger UI 目前不呈现它们。

该问题在此处跟踪https://github.com/swagger-api/swagger-ui/issues/1248

同时你可以使用这个技巧:定义一个default与地图对象相同类型的非必需属性(在下面的示例中),并在描述中给出一些提示:

swagger: "2.0"
info:
  version: 1.0.0
  title: Hashmap
  
paths: {}

definitions:
  MapItem:
    properties:
      firstname:
        type: string
      lastname:
        type: string
  Map:
    description: a (key, MapItem) map. `default`is an example key
    properties:
      default:
        $ref: '#/definitions/MapItem'
    additionalProperties:
      $ref: '#/definitions/MapItem'

此描述不会修改 API 合同并改进文档。

于 2016-05-16T16:03:18.883 回答
5

如果我理解正确,基本问题是 Java Map 没有普遍接受的 JSON 映射,尤其是当键比字符串更复杂时。我已经看到 GSON 采用一种方法(将密钥视为对象),而 Jackson 采用另一种方法(将密钥序列化为字符串)。等效于 Map(字典)的 c# 使用第三种方法(将每个条目视为其自身的键值对象,具有称为“键”和“值”的属性)。由于 Swagger 试图对语言和序列化器不可知,这使其处于不可能的位置。

于 2017-08-10T11:04:14.727 回答
1

通过使用additionalProperties

definitions:
  String-StringStringMap: # <-- use this as your result
    type: object
    additionalProperties:
      $ref: "#/definitions/StringStringMap"

  StringStringMap:
      type: object
      additionalProperties:
        type: string

这会产生一个 2 级地图:

{
  "additionalProp1": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "additionalProp2": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "additionalProp3": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  }
}

使用相同的想法,您也可以指定一个 3 级地图。

于 2021-12-06T21:30:53.933 回答
1

您可以简单地将类型用作对象。当我们从前端解析数据时,我们没有 Map<Key,value> 这样的东西。我们只是发送对象。地图取决于后端的东西。这就是为什么我要求使用 object 作为类型。在对象中,我们可以发送键值对。如下面给出的示例

  metaData:
    type: object
    example: {
      "heading":"comfirmation email"
    }
于 2021-11-29T09:12:50.203 回答