Swagger: карта ‹строки, объекта›

Мне нужно документировать с помощью Swagger 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» страница. Насколько я понимаю, он рекомендует использовать additionalProperties, но, похоже, это не отвечает моим потребностям (или не работает с 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
                }
            }
        }
    }
}

Это почти выполняет свою работу, но читатель должен понимать, что «ключ» может быть любой строкой и может повторяться несколько раз.

Есть ли лучший способ достичь того, что мне нужно?


person Xavier Lamorlette    schedule 21.03.2016    source источник
comment
Лично мне потребовалось некоторое время, чтобы понять почему additionalProperties - правильный ответ: stackoverflow.com/a/41240118/ 110488   -  person Chen Levy    schedule 20.12.2016


Ответы (2)


Использование additionalProperties - правильный способ описания хэш-карты со спецификацией OpenAPI (fka. Swagger), но пользовательский интерфейс Swagger пока не отображает их.

Проблема отслеживается здесь 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 и не улучшает документацию.

person Arnaud Lauret    schedule 16.05.2016
comment
Спасибо, что нашли ссылку на связанную проблему в SwaggerUI. К сожалению, у меня пока недостаточно репутации, чтобы проголосовать за ваш ответ ;-) - person Xavier Lamorlette; 17.05.2016
comment
С этой даты, по крайней мере, javascript-версия swagger-codegen игнорирует дополнительные свойства, так что это может быть препятствием для некоторых - person 1800 INFORMATION; 09.06.2017
comment
дополнительные свойства просто этого не сделают. Дополнительные свойства не учитывают тот факт, что мое значение может иметь определенную схему - person Ajay; 03.05.2019
comment
Отличный ответ, но все еще не ясно, как определить string как тип ключа (в случае $ref как ключа). Это неясно из swagger.io/docs/specification/data-models/dictionaries тоже. - person Dmitriy Popov; 29.12.2020

Если я правильно понимаю, основная проблема заключается в том, что не существует общепринятого сопоставления JSON для карты Java, особенно когда ключ более сложен, чем строка. Я видел, что GSON использует один подход (рассматривает ключ как объект), тогда как Джексон использует другой (сериализует ключ в строку). В C #, эквивалентном Map (Dictionary), используется третий подход (обработка каждой записи как отдельного объекта «ключ-значение» со свойствами, называемыми «Key» и «Value»). Поскольку Swagger пытается быть независимым от языка и сериализатора, это ставит его в невозможное положение.

person John Denniston    schedule 10.08.2017