Swagger: map of <string, Object>

67,848

Solution 1

Using additionalPropertiesis the proper way to describe hashmap with OpenAPI (fka. Swagger) Specification but Swagger UI do not render them for now.

The issue is tracked here https://github.com/swagger-api/swagger-ui/issues/1248

Meanwhile you can use this trick: define a non required property (defaultin the example below) of the same type of the map's objects and give some hint within the description:

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'

This description does not modify API contract and improves documentation.

Solution 2

If I understand it correctly, the basic problem is that there is no universally accepted JSON mapping for a Java Map, especially when the key is more complex than a string. I have seen that GSON takes one approach (treat the key as an object), whereas Jackson takes another (serialise the key to a string). The c# equivalent to a Map (a Dictionary) uses a third approach (treating each entry as a key-value object in its own right with properties called "Key" and "Value"). As Swagger tries to be agnostic to language and serialiser, this puts it in an impossible position.

Solution 3

you can simply use type as object. When we are parsing data from frontend we have no such thing Map<Key,value>. we are just sending objects. Map is up to backend stuf. that is why I am asking to use object as the type. In objects we can send key value pairs. as the example given below

  metaData:
    type: object
    example: {
      "heading":"comfirmation email"
    }

Solution 4

By using additionalProperties:

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

  StringStringMap:
      type: object
      additionalProperties:
        type: string

this results a 2 level map:

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

With same idea you can specify a 3 level map also.

Share:
67,848
Xavier Lamorlette
Author by

Xavier Lamorlette

Updated on July 09, 2022

Comments

  • Xavier Lamorlette
    Xavier Lamorlette almost 2 years

    I need to document with Swagger an API that uses, both as input and output, maps of objects, indexed by string keys.

    Example:

    {
        "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" and "bar" can be any string keys, but they should be unique among the set of keys.

    I know that, with Swagger, I can define an array of objects, but this gives a different API since we then would have something as:

    {
        "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"
            }
        ]
    }
    

    I have read the 'Open API Specification' - 'Add support for Map data types #38' page. As far as I understand, it recommends to use additionalProperties, but it doesn't seem to answer my need (or it doesn't work with Swagger UI 2.1.4 that I use). Did I miss something?

    So far I have found the following work-around (in 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
                    }
                }
            }
        }
    }
    

    This almost does the job, but the reader has to understand that "key" can be any string, and can be repeated several times.

    Is there a better way to achieve what I need?