Defining reusable components with the OpenAPI specification
Tags: openapi, swagger, oas
Published: 2018-01-29 07:39:18

---
title: Defining reusable components with the OpenAPI specification
published: true
description: A call to use fully valid OAS documents for included files
tags: openapi,swagger,oas
---

![OAS building blocks](https://thepracticaldev.s3.amazonaws.com/i/r0fpenaxrgcb3gl3xnng.png)

A pattern I'm seeing increasingly, is to compose [OpenAPI specification](https://www.openapis.org/) (OAS, formerly known as Swagger) documents from multiple files. This allows re-use, easier collaboration and makes larger documents much easier to follow.

The resultant document can be parsed by tools which fully understand and implement the [JSON Reference specification](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) (i.e. they include a resolver), or it can be 'bundled' by de-referencing external references using such a JSON Reference-implementing tool.

But what should those fragments of OAS documents look like?

The OAS specification makes no rulings on this, other than the object being referenced must be of the expected type.

Thus a `parameter` definition in a self-contained OAS document may look like this:

```yaml
...
paths:
  /:
    get:
      parameters:
      - $ref: '#/components/parameters/sort'
...
components:
  parameters:
    sort:
      name: sort
      in: query
      schema:
        type: string
        description: 'The direction of the sort'
        enum:
          - asc
          - desc
```

A parameter referencing an external fragment may look like this:

```yaml
...
paths:
  /:
    get:
      parameters:
        - $ref: './includes/parameters.yaml#/sort'
```

and `parameters.yaml` could simply look like this, with no additional structure:

```yaml
sort:
  name: sort
  in: query
  schema:
    type: string
    description: 'The direction of the sort'
    enum:
        - asc
        - desc
```

If we wished to compose our reusable components across subject-matter areas rather than structurally relating to the OAS, we might structure our documents like this:

```yaml
paths:
  /:
    get:
      parameters:
        - $ref: './includes/parameters.yaml#/parameters/sort'
```

```yaml
parameters:
  sort:
    name: sort
    in: query
    schema:
      $ref: '#/definitions/sortType'
definitions:
  sortType:
    type: string
    description: 'The direction of the sort'
    enum:
      - asc
      - desc
```

The problem with both styles of included document, is that neither is defined by any standard other than being valid JSON or YAML. Neither can be validated against a specification, even though their contents should be composed of valid OAS objects.

It raises questions such as: is it allowable to share the definition of the `sortType` schema across OAS v2 and OAS v3 documents, even though the definition of the Schema Object differs between the two specifications?

I would argue there are significant benefits in always structuring your included documents as fully valid OAS documents.

At the cost of the following six lines of metadata overhead (a little more in JSON), and slightly longer `$ref` values, our `parameters.yaml` document becomes:

```yaml
openapi: 3.0.1
info:
  title: An include file to define sortable attributes
  version: 1.0.0
paths: {}
components:
  parameters:
    sort:
      name: sort
      in: query
      schema:
        $ref: '#/components/schemas/sortType'
  schemas:
    sortType:
      type: string
      description: 'The direction of the sort'
      enum:
        - asc
        - desc
```

This document now has the benefits that it can be validated, linted, converted, transformed and edited using OAS compliant [tools](http://openapi.tools). In the case of conversion, it means OAS v2 document fragments can be upgraded in place to OAS v3 without having to bundle the document into a monolith.

The minimal `info` object gives us properties to describe the expected usage of the fragment, and an ability to version it separately from the 'master' OAS documents which reference it.

Simply by the presence of the empty `paths` object, we can tell we are dealing with a fragment, not a fully-defined OAS document.

These reusable sub-documents can also be shared between projects, allowing for industry-specific standard components to emerge.