OpenAPI v3.1 and JSON Schema
Updated 2019-05-29: OpenAPI v3.1 has dropped SemVer, so a few things that were going to be deprecated are now just straight up removed. This post has been updated to reflect that.
Updated 2021-01-10: JSON Schema released Draft 2020-12 which clarified a few edge cases, it's not a meaningful change to the content of the article but we've replaced references to 2020-12 to avoid future confusion.
OpenAPI using an "extended subset" of JSON Schema has caused confusion in the API space since before I had even heard of OpenAPI. Thanks to a lot of hard work from a lot of people over the last 6 months, OpenAPI v3.1 will in fact solve this problem, and there was much rejoicing.
For anyone who's not read a million words on the topic from me on this topic already, I was talking about the divergence in 2017, 2018, creating workarounds, suggesting functionality, complaining about that functionality... Everyone in and around OpenAPI was trying to get something done to solve this problem. For all this time, often unaware of any of the discussions, the divergence was a constant pain in everyone's ass: tooling vendors and end-users alike.
Well, good news. OpenAPI v3.1 has brought along some substantial change. For a while we thought we'd see a few of OpenAPI-special keywords deprecated, and the JSON Schema keywords and functionality supported, but this "two ways of doing something" was not looking good for tooling vendors. So, after much consideration, OpenAPI v3.1 has dropped SemVer in order to more quickly and easily properly align itself with JSON Schema. Here's an overview:
- OpenAPI Schema is a vocabulary of JSON Schema 2020-12
- type arrays are now supported
- nullable has been removed
- arbitrary keywords are now supported without needing an
x-on the front
- exclusiveMinimum and exclusiveMaximum take a numeric value instead of being a boolean
- discriminator is deprecated, and miiiight still be removed before OpenAPI v3.1 final happens
Let's look at some of this a bit closer.
Check out this new wording from the OpenAPI Specification.
The OpenAPI Schema Object is a JSON Schema vocabulary which extends JSON Schema Core and Validation vocabularies. As such any keyword available for those vocabularies is by definition available in OpenAPI, and will work the exact same way.
There are no more "missing" JSON Schema properties. If a keyword exists in JSON Schema Draft 2020-12 (Core or Validation), then it's good to use in OpenAPI v3.1.
How about keywords which worked... differently?
The most common source of confusion for many people was that
type could be an array of strings in JSON Schema, but had to be a single string in OpenAPI v2-3. In OpenAPI v3.0 you could at least use oneOf to select multiple types, meaning that three different ways to do the same thing were possible, with some tooling supporting one, two, or three of them...
type: string# no integers allowed... 🤷♂️
oneOf:- type: string- type: integer
type: [string, integer]
OpenAPI v3.1 is now happy to take a type array!
Users of languages like Java and C++ will still wonder why anyone would ever do this, but tooling vendors building tools for this can just treat it as they did a
type: stringnullable: true
type: [string, "null"]
This is probably the biggest breaking change, but it's such an easy find and replace. You can even use tools like openapi-schema-to-json-schema to upgrade your schema files (so long as you've been keeping them DRY!)
JSON Schema Draft 2020-12 added a few new formats so go wild with those. There are some changes to how formats are interpreted now, and they are being relaxed from validation, to annotations which could be used for validation if configured to do so.
Basically, trying to validate that data follows the rules for what a specific validation tool things is valid for that format is... awful. Different tools disagree about what an email address is, despite there being a standard for what a valid email address is.
Tool vendors can feel free to keep existing format validation, but probably move it behind a config switch. Maybe the next major version of that tooling could have it default off.
Every now and then somebody would add arbitrary keywords to their JSON Schema files to keep track of information that special (maybe in-house) tooling understood, but were not part of the JSON Schema spec. Then they'd try and use those JSON Schema files in OpenAPI, only to find it blows up. This was also fixed.
In addition to the JSON Schema properties defined in the vocabularies defined in the JSON Schema Core and JSON Schema Validation specifications, any properties can be used from any vocabularies, or entirely arbitrary keywords.
OpenAPI v3.0 would only allow "extensions", which were arbitrary keywords starting with
x-. Now, no need for the
x-, unless you like it, in which case carry on. 👍
JSON Schema has
examples which is a bare array, which means you can have a string with two possible examples like this:
type: stringexamples:- squirtle- charmander
Documentation tools could chose to show the first one, or both, doesn't matter they're both good choices.
OpenAPI v3.0 was a little different:
type: stringexample: squirtle
JSON Schema based tooling would not know what
example was, and OpenAPI tooling would choke when it saw
examples because it is not a valid keyword inside the Schema Object.
In OpenAPI v3.1 the Schema Object
example keyword is deprecated, so you should start using
examples in your API description documents.
I will probably add a Spectral rule for that to help nudge people in the right direction.
The change above does solve a discrepancy, but it does unfortunately introduce its own little bit of confusion. Hold onto your butts.
OpenAPI v3.0 Schema Objects do not have
examples as a keyword, but there is a totally unrelated
examples which shows up elsewhere in OpenAPI v3.0 (in the Media Type Object, for request and responses). Don't mix them up, they act differently.
Let's take a look at this not-in-the-schema approach to examples which OpenAPI offers:
parameters:- in: queryname: limitschema:type: integermaximum: 50examples: # Multiple exampleszero: # Distinct namevalue: 0 # Example valuesummary: A sample limit value # Optional descriptionmax: # Distinct namevalue: 50 # Example valuesummary: A sample limit value # Optional description
Example from Swagger.io talking about Examples.
responses, outside of the Schema Object, there is a special OpenAPI keyword called
examples. This is not a bare array like the JSON Schema
examples, but an object where the keys are names, and the example has to go inside the
This confusion of two types of
examples is going to persist, but at least this problem can be solved with documentation and tutorials, instead of being a roadblock making files be unusable in some tooling but fine in others. 😅
JSON Schema made an improvement to how exclusiveMinimum and exclusiveMaximum work. In older versions, they were a boolean switch which would suggest that the minim value defined was also an acceptable value.
# Value has to be 21 or overminimum: 21# Value has to be greater than 21, not 21minimum: 21exclusiveMinimum: true
# Value has to be 21 or over (same)minimum: 21# Value has to be greater than 21, not 21 (new!)exclusiveMinimum: 21
This is a small change, and has be done to simplify things. Keywords in schema objects generally should not effect other keywords in unexpected ways, so this keyword now just handles its own business.
The work for JSON Schema alignment is pretty much done, but there are a few licks of paint until its completely sorted. These tweaks might come in over the course of the release candidate process, the first of which is supposedly going to be the end of February (this month?! 🤯)
OpenAPI v3.1 has a bunch of other cool stuff coming too:
- Webhooks which do not have to be documented as callbacks underneath a specific operation
pathsis now optional so an API description could be Webhooks only
- Maybe overlays will be a thing
We'll talk about all this in future articles in the future. Until then, make sure your tooling is ready for JSON Schema 2020-12 and OpenAPI v3.1. Many tooling vendors are hard at work on this as we speak, with a few validation tools already done:
Head over to the official JSON Schema Implementations list of all sorts of tooling as they're released.
Hopefully soon this will all be behind us.
Get the newsletter
Pragmatic API, HTTP And REST info monthly