Claudiu
Claudiu

Reputation: 229291

How can I specify that an object's type is one of several possible object types?

I have an API where I post a set of object to the server, differentiated by type, where each type has some different parameters. The commands are structured like so:

{
    "type": <command-name>,
    "args": { 
        <command-specific args>
    }
}

For example, these may be two possible commands:

{
    "type": "Flooblinate",
    "args": {
        "intensity": "High",
        "frequency": "Every blue moon"
    }
}

{
    "type": "Blagostrate",
    "args": {
        "temperature": 34.5,
        "darkMatter": true
    }
}

How can I specify this in Swagger? I can specify an enum for "type", but how do I say ""args" is one of these possible objects"?

I've checked out the docs but nothing stands out. The most promising one was allOf because it displayed nicely in the editor (pastebin, paste into the online editor):

definitions:
  Product:
    type: object
    allOf:
    - type: object
      title: Flooblinate
      properties:
        intensity:
          type: string
        frequency:
          type: string

    - type: object
      title: Blagostrate
      properties:
        temperature:
          type: number
        darkMatter:
          type: boolean

Which looks like this:

enter image description here

However, this isn't semantically what I need, and, not surprisingly, in the online viewer (that one's not set up for my test case, not sure how to link up a local file easily), they are presented as if all the fields appear at the same time, which is of course what allOf means:

enter image description here

What's the proper way to represent this with Swagger?

Upvotes: 2

Views: 164

Answers (1)

Claudiu
Claudiu

Reputation: 229291

According to input from Ron on the google group, what I want is to use the discriminator property:

definitions:
  Product:
    type: object
    discriminator: type
    properties:
      type: string
    required: [type]
  Flooblinate:
    allOf:
    - $ref: '#/definitions/Product'
    - type: object
      properties:
        intensity:
          type: string
        frequency:
          type: string
  Blagostrate:
    allOf:
    - $ref: '#/definitions/Product'
    - type: object
      properties:
        temperature:
          type: number
        darkMatter:
          type: boolean

Semantically this means what I want it to mean. I should specify $ref: '#/definitions/Product' wherever the API accepts or returns any one of Flooblinate or Blagostrate. Note this requires a field (called type here) on the objects to act as the discriminator.

I thought this may be the approach, but the tools didn't show what I expected. However:

That's because the tools are not 100% in support of the discriminator yet - however, that's the right way to describe your use case. Once you define the discriminator in the top level model, anything that 'allOf's it will be considered a viable option, and indeed you're refer to the top level model for usage.

Upvotes: 1

Related Questions