DEV Community

Mike Ralphson
Mike Ralphson

Posted on • Edited on

Defining reusable components with the OpenAPI specification

OAS building blocks

A pattern I'm seeing increasingly, is to compose OpenAPI specification (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 (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:



...
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


Enter fullscreen mode Exit fullscreen mode

A parameter referencing an external fragment may look like this:



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


Enter fullscreen mode Exit fullscreen mode

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



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


Enter fullscreen mode Exit fullscreen mode

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:



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


Enter fullscreen mode Exit fullscreen mode


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


Enter fullscreen mode Exit fullscreen mode

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:



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


Enter fullscreen mode Exit fullscreen mode

This document now has the benefits that it can be validated, linted, converted, transformed and edited using OAS compliant 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.

Top comments (11)

Collapse
 
nikolaymartynov profile image
Nikolay Martynov

You say:

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

But spec maintainer thinks differently:

It's meant to describe APIs, not catalogs of objects that can be used in APIs.

Source: github.com/OAI/OpenAPI-Specificati...

Collapse
 
mikeralphson profile image
Mike Ralphson

That's what Ron Ratovsky said some time ago. He's allowed to change his mind. :)

Ron is also one of the maintainers, but then so am I...

Collapse
 
nikolaymartynov profile image
Nikolay Martynov

Personally, I've recently made a study to compare different options to define the structure of the data exchanged between the systems using JSON encoding. The final choice I had to make was not OpenAPI because:

  • I really want to be able to talk just about the data. It might be RPC. It might be messaging. But the data will be (mostly) the same. Of course, you also want to define transport thingies like paths and response codes as well once you get to it. But the data and its structure exchanged by the systems are largely independent of particular transport.

  • I fear that once unapproved workaround like empty paths is added, the tooling support could degrade rapidly. Again, talking about the data, I would like to be able to validate JSON file for compliance with defined structure. I want to be able to do this in runtime, during build time and when editing the schema or file with data. Most tools for OpenAPI are around REST and it is not quite trivial to validate chunk of data.

Thread Thread
 
ccristian profile image
Cristian Chiovari

So what was your choice ?

Thread Thread
 
nikolaymartynov profile image
Nikolay Martynov

Schema language for BLA-BLA-BLA unified format

Changes

  • 1.0 – Initial version

Executive summary

It is recommended to use JSON Schema to define JSON encoding of unified format of BLA-BLA-BLA.

Introduction

Unified format for BLA-BLA-BLA needs a formal protocol definition. For this, a schema definition language should be chosen. A universal schema definition language that can be used to define data structures that can later be expressed using several encoding formats like XML and JSON are preferred. However, this is not a mandatory requirement since industry moves away from XML while JSON adoption grows larger and larger. Thus, support for JSON is mandatory requirement while support for other technologies is optional.

Schema definition language should have good tooling support:

  • For schema authoring
  • For data authoring
  • For validating data compliance to schema (Java)

Schema definition language should have wide adoption in the industry to avoid usage of a dead or rare technology.

JSON Schema

Home

  1. json-schema.org/

Official learning

  1. json-schema.org/understanding-json...
  2. json-schema.org/learn/file-system....

Specification

  1. json-schema.org/latest/json-schema...
  2. json-schema.org/latest/json-schema...

Books

  1. learning.oreilly.com/library/view/...
  2. learning.oreilly.com/library/view/...
  3. learning.oreilly.com/library/view/...
  4. learning.oreilly.com/library/view/...
  5. learning.oreilly.com/library/view/...
  6. learning.oreilly.com/library/view/...

Tooling

Validate sample by schema – build

  1. github.com/alenkacz/gradle-json-va...

Validate sample by schema – runtime

  1. github.com/everit-org/json-schema
  2. github.com/leadpony/justify

Validate sample by schema – support

  1. jsonschemavalidator.net/
  2. jsonschemalint.com/#/version/draft...

Schema authoring

  1. jsonschema.net/

Data authoring

  1. IntelliJ IDEA supports JSON and validation by JSON Schema out of the box

Summary

3GPP TS 28.541 uses JSON Schema to define data model.

Very good candidate to describe JSON data format independent of API/RPC/etc. Tooling support is good enough. However, while it is widely adopted, the specification is not yet finalized. This creates a risk that specification might change in incompatible way and schema will have to be adjusted.

Yang

Home

  1. Not found reliable community home

Official learning

  1. Not found

Specification

  1. RFC 6020: YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)
  2. RFC 6110: Mapping YANG to Document Schema Definition Languages and Validating NETCONF Content
  3. RFC 6991: Common YANG Data Types [obsoletes RFC 6021]
  4. RFC 7950: The YANG 1.1 Data Modeling Language [replaces RFC 6020]
  5. RFC 7951: JSON Encoding of Data Modeled with YANG
  6. RFC 7952: Defining and Using Metadata with YANG
  7. RFC 8342: Network Management Datastore Architecture (NMDA)
  8. RFC 8525: YANG Library [obsoletes RFC 7895]
  9. RFC 8528: YANG Schema Mount

Books

  1. learning.oreilly.com/library/view/...

Tooling

Validate sample by schema – build

  1. github.com/GianmarcoBruno/json-yang (uses Python)

Validate sample by schema – runtime

  1. Not found

Validate sample by schema – support

  1. Not found

Schema authoring

  1. sysrepo.org/YANG-Creator
  2. marketplace.eclipse.org/content/ya...

Data authoring

  1. marketplace.eclipse.org/content/ya...

Summary

3GPP TS 28.541 uses Yang to define data model.

While Yang model is independent of encoding and Yang supports both XML and JSON, it seems to be a bad choice. The reasons are:

  • Little adoption across industry
  • Poor tooling support
  • High complexity

OpenAPI

Home

  1. openapis.org/

Official learning

  1. swagger.io/docs/specification/about/

Specification

  1. github.com/OAI/OpenAPI-Specificati...

Books

  1. learning.oreilly.com/library/view/...
  2. learning.oreilly.com/library/view/...
  3. learning.oreilly.com/library/view/...
  4. learning.oreilly.com/library/view/...
  5. learning.oreilly.com/library/view/...

Tooling

Validate sample by schema – build

  1. gitlab.com/mmalawski/openapi-valid... (php)

Validate sample by schema – runtime

  1. github.com/RepreZen/KaiZen-OpenAPI...

Validate sample by schema – support

  1. Not found

Schema authoring

  1. studio.apicur.io/
  2. marketplace.eclipse.org/content/ka...
  3. editor.swagger.io/

Data authoring

  1. marketplace.eclipse.org/content/ka...
  2. editor.swagger.io/

Summary

Is not a data format definition language but API definition language. Requests to allow it to define the data are rejected. Quote: “It's meant to describe APIs, not catalogs of objects that can be used in APIs.” Source: github.com/OAI/OpenAPI-Specificati... While there are technical ways to circumvent this, this is discouraged by language designers. It is risky since the tools are unlikely to support validation once these workarounds are in place.

OpenAPI is based on JSON Schema but has additional restrictions to define APIs. One can be converted to another manually and using specialized tools.

OpenAPI is used to define 3GPP TS 28.532 and TMF 642 APIs.
Due to complexity and restrictions for usage as data format schema rather than API schema, it is recommended to use a better alternative when available.

Collapse
 
elmuerte profile image
Michiel Hendriks

Why overload the the semantics of path and not simply add a "fragment: true" to the info object? ("x-fragment" until it is adopted in the standard)

Sure, it does not make much sense to have an API with no paths. But it will make it explicit that the specification is a fragment.

Collapse
 
mikeralphson profile image
Mike Ralphson

The presence of paths: {} isn't intended to overload the meaning, it's because paths is a mandatory object in the OAS (2.0 and 3.0.x), although it can be empty.

x-fragment is a good idea to make that explicit.

Collapse
 
harej profile image
James Hare

Thank you for this post.

Currently I am working on a software project to develop a catalog of software tooling. As part of this project, I have developed a JSON Schema for describing tools. I want to avoid repeating myself, so I would like to incorporate this schema into my API contract which I am currently writing in OpenAPI 3.0. Do you think it would be problematic if I just incorporated the schema directly, even though I would be embedding a JSON Schema document into an OpenAPI document? What do you generally recommend for interoperability between the two?

Collapse
 
mikeralphson profile image
Mike Ralphson

If you can limit yourself to the common subset of JSON Schema draft 5 and OpenAPI 3.0 schema objects, you'll be fine. If that's a problem, take a look at speccy (github.com/wework/speccy) which implements a filter to convert JSON Schema to OAS schema objects, using github.com/wework/json-schema-to-o...

Collapse
 
mikeralphson profile image
Mike Ralphson • Edited

Another possible approach is to use the x-oas-draft-alternativeSchema extension (github.com/OAI/OpenAPI-Specificati...) although as this is brand new, we don't yet know of any implementations - so would probably only suit your own tooling.

Collapse
 
krutikkhatri profile image
krutikkhatri

Hii
You can also use onlinejsontools.org/ for json validator,beautify,minify,xml,yaml,CSV,bson,plain text,base64,tsv.
Do checkout this site!