How can I define a Map with arbitrary keys in a Swagger model

Dave Sag picture Dave Sag · Apr 16, 2015 · Viewed 7k times · Source

How can I define a map with arbitrary keys in a Swagger model

Say I have the following internationalised model (in Ruby-style pseudocode, assuming use of something like Globalize)

class Thingy
  translates :name
  attribute :code
end

and my API wishes to be able to return something like

{
  "thingy": {
    "code": "barn", 
    "translations": {
      "default": "barn", 
      "en": "barn", 
      "ru": "cарай", 
      "fr": "grange", 
      "nl": "schuur"
    }
  }
}

but I don't want to restrict the range of translation keys in the actual API

I can define in my swagger doc

definitions:
  thingy:
    required:
      - code
    properties:
      code:
        type: string
    additionalProperties:
      translations:
        required:
          - default
        property:
          default:
            type: string
        additonalProperties: string

That validates but the Swagger Codegen won't generate anything off the additionalProperties and it's not very explicit compared to somehow being able to define a map type with a mix of required and arbitrary keys.

Anyone working with internationalisation is going to face similar issues so my question is, how have other people dealt with this scenario?

Answer

jreece picture jreece · Apr 16, 2015

This works under swagger-codegen-2.1.1-M1 (Java/JavaJaxRS) ... with Ron's suggestions ...

The YAML ...

translation:
  required:
    - default
  properties:
    default:
      type: string
  additionalProperties:
    type: string

thingy:
  required:
    - code
  properties:
    code:
      type: string
    translations:
      $ref: '#/definitions/translation'

creates a Map with a 'default' attribute ...

public class Translation extends HashMap<String, String> {

    /**
     * 
     */
    @Expose
    private String _default = null;

    /**
     * @return  _default the _default
     */
    public String getDefault() {
        return _default;
    }

    /**
     * @param  _default to set
     */
    public void setDefault(String _default) {
        this._default = _default;
    }

}

Which in turn is embedded in a Thingy .....

public class Thingy  {

    /**
     * 
     */
    @Expose
    private String code = null;

    /**
     * 
     */
    @Expose
    private Translation translations = null;

    /**
     * @return  code the code
     */
    public String getCode() {
        return code;
    }

    /**
     * @param  code to set
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @return  translations the Translations
     */
    public Translation getTranslations() {
        return translations;
    }

    /**
     * @param  translations the Translations to set
     */
    public void setTranslations(Translation translations) {
        this.translations = translations;
    }

}