OpenAPI/Swagger - Tweaking your JSON output

Image by cwright1 from Pixabay

This week I got my first chance to use the OpenAPI spec, you might have heard it called Swagger. It’s a common way to define APIs. It’s great because it can autogenerate both client and server code, and even documentation on how to use the API that you create.

There is plenty to read about OpenAPI/Swagger, but I want to focus on one particular part that I struggled a bit with and talk through how I reconciled it.

Our application, like most these days, is expected to consume and produce JSON. This is no problem for OpenAPI/Swagger because it allows you to define Media Types as part of the definition. So you can easily return JSON, XML, or anything else.

I needed to return a list of Groups. For this writing, I will simplify the Group such that it only has a “name” and a “description”. So, if you look at the example on the Swagger site you can see how to define an array. It looks like this:

type: array
items:
  type: object
  properties:
    id:
      type: integer

So, for our list of Groups, we’ll tweak this to:

type: array
items:
  type: object
  properties:
    name:
      type: string
    description:
      type: string

This would produce JSON output that looks like the following :

[{
  "name": "MyName",
  "description": "Test description"
}, {
  "name": "Other Group",
  "description": "Test 123"
}]

Not bad!

But then I realized, I don’t want my JSON output to be a top-level Array. I always prefer to return Objects. This makes it easier to modify down the line if I need to add additional fields, like additional Objects/Arrays, etc. An example would be some metadata about the response, such as how long the request took, or how many total Groups there are.

I had trouble finding any rules that say “Don’t return an Array”. The closest thing i could find was this REST site that shows Objects being returned. Since this is what I’ve grown accustomed to, and because this is how Mirage JS returns its data, I figured I was on a good path.

If you have any links or documentation that talks about Best Practices around JSON Arrays, please share in the comments below!

So, what I really want my data to look like is:

{
  "groups": [{
    "name": "MyName",
    "description": "Test description"
  }, {
    "name": "Other Group",
    "description": "Test 123"
  }]
}

To make this happen, we need to tweak our YAML a bit. We’ll introduce an Object that wraps the Array:

type: object
properties:
  groups:
    type: array
    items:
      type: object
      properties:
        name:
          type: string
        description:
          type: string

And there you have it! The JSON that is returned is an Object with a “groups” Array ! Once I change my client code to use response.groups instead of response, everything works as expected.

I hope this has been helpful. I’ve written my own JSON responses in various languages, not really thinking too much about it. I now see the benefit of OpenAPI/Swagger, as it provides a robust, language agnostic, way to describe and define your APIs. This is especially important in a large enterprise. I expect to be doing a lot more with it in the future. Thanks for stopping by!