Home>Blog>
How OpenAPI Data Types Enable Robust APIs

How OpenAPI Data Types Enable Robust APIs

How JSON and JSON Schema impacted the OpenAPI format and what’s possible with your API descriptions.

Design Quality APIs 10x Faster

Try Stoplight

Many early APIs were under-documented, which left large questions about what data to expect in return. Perhaps they could get away with this uncertainty because many were experimental projects. Today, software depends on these API interfaces. In fact, they’re central to any software-driven company, which includes most medium and large businesses.

The OpenAPI specification makes more robust APIs possible. Specifically, OpenAPI data types, declared for every field in an API, allow developers to ensure live data matches expectations. Much of the guesswork and manual labor is removed from API development with a complete and accurate OpenAPI document. In this post, we’ll look at how JSON and JSON Schema impacted the OpenAPI format, as well as what’s possible with your API descriptions.

🔗 🔗 Why JSON Needed JSON Schema

The JSON data format emerged as a subset of JavaScript In the early 2000s. Within a few years, Yahoo! and other companies with emergent APIs used JSON as an option. By the 2010s, XML was no longer the favored format. The lightweight, flexible JSON had clearly become the developer choice. However, some of the XML lessons of data types and strict schemas were set aside—which set the stage for JSON Schema.

JavaScript is an untyped language, which means any variable can contain any of a handful of values. When translated to JSON, the format supports these data types:

  • number: such as 101, 3.14, or -17
  • string: “any number of characters surrounded by quotes”
  • boolean: true or false
  • null: literal empty value

In addition, there are two types that can include the above types—or each other:

  • object:{“key”: “value pairs”, “num”: 101}
  • array: [“list”, “of”, null, “any values”, true, 101, false]

There are an upside and downside to JSON’s flexibility. It’s easy to use and most modern languages can easily parse it into a native structure. However, exact data types need to be implied. The JSON grammar describing a number, for example, covers every potential permutation of number types.

Diagram

Many typed languages at least separate integers (whole numbers and their negative counterparts) from floating-point numbers (those including a decimal point). The accepted range of values within these two types can also vary. For example, a 32-bit integer can not be larger than 2,147,483,647.

Where the JSON grammar only describes the general format of data, JSON Schema is used to provide specific field names to expect within particular JSON objects. For example, you may have a company model you use to describe customer organizations. JSON Schema lets you declare the fields that can or must be present.

JSON Schema data types are the same as JSON, with the exception that integers are separated out from the generic number type. JSON Schema also goes farther with what to expect within your data, including formats and ranges of potential values.

To highlight some of these differences, here is a simple JSON Schema for a company model:

{
  "title": "Company",
  "description": "Company record details",
  "required": [ "company_id", "name" ],
  "type": "object",
  "properties": {
    "company_id": {
      "type": "string",
      "minLength": 12,
      "maxLength": 12,
      "description": "Unique identifier for this company"
    },
    "name": {
      "type": "string",
      "description": "The company name."
    },
    "employees": {
      "description": "Number of people employed by this company.",
      "type": "integer",
      "minimum": 0
    }
  }
}

In this basic example, a customer will always have name and company_id fields. Both are strings, but the ID is exactly 12 characters. Optionally, an employees field will display the number of employees as a non-negative integer.

Many developers use JSON Schema on its own, but the format also provides the foundation for the OpenAPI specification’s data types. In the next section, you’ll see how to get specific with data types using an OpenAPI description.

🔗 🔗 OpenAPI Provides Context to Your Schemas

The JSON data format simply declares what data types can be described. JSON Schema defines fields, data types, requirements, and allowed value ranges. When it comes to using JSON with APIs, it’s clear how JSON Schema is useful. However, there’s another step to declare what part of an API expects what schema. That’s where OpenAPI and its JSON Schema-inspired data types come in.

OpenAPI uses JSON Schema (with minor exceptions the community is working through) as the basis for describing API request and response data. These are combined with the paths and other elements of an API that can be described by OpenAPI 3.0.

Here is the same JSON Schema model from the previous section, now included in an OpenAPI document:

{
  "openapi": "3.0.0",
  "info": {
    "title": "company",
    "version": "1.0"
  },
  "servers": [
    {
      "url": "http://api.example.com"
    }
  ],
  "paths": {
    "/company/{id}": {
      "parameters": [
        {
          "schema": {
            "type": "string",
            "minLength": 12,
            "maxLength": 12
          },
          "name": "id",
          "in": "path",
          "required": true,
          "description": "12 character company identifier"
        }
      ],
      "get": {
        "summary": "Your GET endpoint",
        "tags": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/company"
                }
              }
            }
          }
        },
        "operationId": "get-company-id",
        "description": "Retrieve a specific company"
      }
    }
  },
  "components": {
    "schemas": {
      "company": {
        "title": "company",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 12,
            "maxLength": 12
          },
          "name": {
            "type": "string"
          },
          "employees": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "name"
        ]
      }
    }
  }
}

Whether a developer is reading these requirements or they’re interpreted as part of integration testing, the allowed values for individual fields is clear. When retrieving a specific company, you get back a 12 character ID string, a name string, and optionally an employee count. If the last value is present, it must be an integer of zero or higher (no such thing as negative employees).

With the schema stored as a component, it can be referenced from other areas of the OpenAPI document, as well. For example, here is a POST request to create a new company record:

    "/company": {
      "post": {
        "summary": "",
        "operationId": "post-company",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/company"
                }
              }
            }
          }
        },
        "description": "Add a new company record",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }

The object above could simply be added to the existing array of paths in your OpenAPI document.

While this post has focused exclusively on JSON, it’s important to note it’s not the only format supported by OpenAPI. The API descriptions themselves can also be written in YAML, even when describing JSON responses. For example, here is the component section and company schema in YAML format:

components:
  schemas:
    company:
      title: company
      type: object
      properties:
        id:
          type: string
          minLength: 12
          maxLength: 12
        name:
          type: string
        employees:
          type: integer
          minimum: 0
      required:
        - id
        - name

OpenAPI can also describe other response formats, such as XML. Its flexibility allows the OpenAPI specification to be used to document most REST APIs, which covers the majority of APIs in production.

With OpenAPI data types defined, developers can build and use intelligent tooling around their API development.

🔗 🔗 API Testing and Automation Put OpenAPI Into Action

Before API descriptions like OpenAPI (and its predecessor, Swagger), there were a lot more questions and assumptions involved in API development. API consumers could infer data types from example responses, the JavaScript way. But that left manual effort for developers of typed languages. And any automation or robust testing was difficult or impossible.

As we’ve seen, OpenAPI documents include not just data types, but additional format details. Both providers and consumers can use this intelligence to perform data validation automatically. Stoplight’s open-source tools can help automate your OpenAPI development:

  • Spectral is a linter to ensure your OpenAPI documents are complete
  • Prism is an input/output validator to test a live API against an OpenAPI document

In addition, Prism can build mock servers to stage your API interfaces, including realistic generated data in an accurate format based on your OpenAPI data types.

By declaring the schemas your API accepts and produces, you enable all kinds of automation. You can generate accurate structures in your client libraries and SDKs. Similarly, you can stub out your API servers themselves—just add the live data to complete the interface. Much of the work is done as part of your API design, when you determine what endpoints, fields, and data types will be part of your interface.

The result is a more robust API, which enables all sorts of automation opportunities because your OpenAPI document provides a clear description of what’s expected.

Read how world’s leading API first companies are solving API Design Management at Scale.
Get the API Design Guide