TS-29: JSON Schema

This technical standard sets out some guidelines for JSON schema. The emphasis on this technical standard is on designing JSON schema, though there is also some information on using published JSON schemas such as JSON-LD.

JSON Schema provides a vocabulary for describing the structure of JSON data. Documentation, code, and other artifacts can be generated from JSON Schema definitions, but the primary use case if to validate JSON documents.

JSON schema is commonly used to define the structure of data transferred between systems via network APIs. It may also be used for input validation, to define interfaces for data structures constructed at runtime, and to define data persistence schema (eg. document stores).

Content type

The official content type for JSON Schema is application/schema+json. It is RECOMMENDED to use this content type when serving JSON Schema via HTTP.

Versions

JSON Schema was originally defined as an IETF standard, but is now maintained as a community project. Versions 00 through 04 were published as IETF drafts, while draft-05 moved to the community project.

The current version of JSON Schema is Draft 2020-12. It is RECOMMENDED to use this version for new projects. The metaschema for this version is https://json-schema.org/draft/2020-12/schema.

Cross-references

JSON Schema defines a $ref keyword to link schema from other schema.

It is RECOMMENDED to use $ref to share common structures, keeping schemas modular and reusable. Prefer schema composition over inheritance. Designing your schema for modularity is how, like code, you can best manage growing complexity at scale.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Locale",
  "description": "Locale, composed from a BCP-47 language tag, ISO-3166 alpha-2 country code, and Olsen IANA timezone ID.",
  "type": "object",
  "required": [
    "country_code",
    "language"
  ],
  "properties": {
    "country_code": {
      "$ref": "country-code.schema.json"
    },
    "language": {
      "$ref": "language-code.schema.json"
    },
    "timezone": {
      "$ref": "timezone.schema.json"
    }
  }
}
Example

However, as per the JSON Schema documentation, it is RECOMMENDED to not require client applications to automatically resolve schema that are referenced from other schema via the $ref attribute. Instead, it is RECOMMENDED that JSON Schema publishers automatically swap $ref properties for inline schema, using a build step.

A command-line tool is available to do this.

JSON Hyper-Schema

JSON Hyper-Schema is an extension to JSON Schema that adds properties to allow the embedding of hypermedia links in JSON documents. It builds on URI Templates (RFC 6570) and other standards.

The main use case for JSON Hyper-Schema is to embed hypermedia controls in JSON documents that enable APIs to be navigated, and explored in a dynamic way (ie. without clients necessarily having initial knowledge of all available resources and endpoints).

The following example, taken from the specification, adds a single link:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "number",
      "readOnly": true
    }
  },
  "links": [
    {
      "rel": "self",
      "href": "thing/{id}"
    }
  ]
}

JSON Hyper-Schema adds the links property, which must be an array of "link description objects" (LDO).

Any IANA-registered link relation type can be used to define the link relation type (rel). This defines the semantics of the link in terms of its relationship to the resource. The table below describes some of the most commonly used link relation types.

Type

Description

self

Identifies the resource itself.

next/prev

Indicates the next or previous resource in a sequence, eg. in a paginated list.

first/last

Refers to the first or last resource in a sequence.

up

Refers to a parent resource in a hierarchy of resources.

It is RECOMMENDED to use a small subset of link relation types, and to use them consistently across all endpoints in a hypermedia API. You SHOULD NOT define custom relations, unless absolutely necessary when no standard ones fit the use case.

The following best practices also apply for JSON Hyper-Schema:

  • Each response should contain minimal links, just enough for clients to navigate deeper.
  • Do not expose an entire API graph in any single response, except for simple APIs composed of just a few endpoints.
  • It is RECOMMENDED to always include "self" links to the current resource, wherever relevant.
  • Use simple, minimalist URI templates, with only necessary path parameters (variables).
  • Provide all required template variables in the response object.
  • Use templatePointers to clearly map data to template variables.
  • Use targetSchema to describe expected response formats.
  • Use targetHints for media types and methods.
  • Add title properties for human-readable link descriptions.

OpenAPI

OpenAPI is another dialect of JSON Schema, used to describe HTTP "RESTful" APIs. It is a superset of JSON Schema, adding additional properties to describe HTTP-specific concepts.

for all JSON Schema, but there are a few OpenAPI-specific things to keep in mind.

JSON-LD (JSON for Linked Data)

JSON-LD is a schema used to imbue JSON documents with semantic meaning and to embed linked data.

JSON-LD bridges the gap between concepts from the semantic web and modern web service APIs. The idea is that machines can understand and explore data in JSON documents, similarly to how semantic web technologies like RDF and OWL work.

JSON-LD defines two main properties:

  • @context references a vocabulary that describes the concepts in the document.
  • @type indicates the type of the entity represented by an object.

Schema.org is perhaps the most popular vocabulary for JSON-LD. Its vocabulary can also be embedded in HTML documents using microdata or RDFa.

{
  "@context": "https://schema.org",
  "@type": "Person",
  "name": "Jane Doe",
  "jobTitle": "Professor",
  "telephone": "(425) 123-4567",
  "url": "http://www.janedoe.com"
}

It is RECOMMENDED to reuse existing vocabularies, such as Schema.org, wherever there is a good fit for an application’s schema. Even if a vocabulary does not cover all the concepts required by the application, it is still better to try to reuse existing vocabularies, even if only partially. This saves time and effort designing new schemas, and it also helps to keep data as interoperable as possible with other systems. Even if interoperability is not a requirement now, it may be in the future.

For example, Schema.org’s Person type, which defines properties such as givenName, familyName, jobTitle, and telephone, is a good basis from which to design a schema for users, customers, or other such entities.

For further guidance on using JSON-LD, the W3C maintains a JSON-LD Best Practices document.

JSON Pointer

IETF RFC 6901 defines a syntax for identifying a specific value in a JSON document. A JSON Pointer is a string beginning with a forward slash /, with each subsequent slash separating path segments that identify nested objects and arrays:

/path/to/property

Elements of arrays can be referenced using zero-indexed numeric indices:

/users/0/name

An empty string "" refers to an entire document.

There are a couple of special characters. The / character in a property name is escaped as ~1. The ~ character is escaped as ~0. It is RECOMMENDED to not include these, or any other special characters, in property names, to make traversal of JSON data structures as easy as possible for all clients.

JSON Pointer is used for data extraction, validation, and transformation. It is also used for partial updates via JSON Patch operations. Relevant to this technical standard, JSON Pointer syntax is RECOMMENDED for creating cross-references within JSON documents. Example:

{
  "categories": [
    {
      "id": "electronics",
      "name": "Electronics"
    },
    {
      "id": "computers",
      "name": "Computers",
      "parentCategory": "/categories/0"
    },
    {
      "id": "laptops",
      "name": "Laptops",
      "parentCategory": "/categories/1"
    }
  ],
  "products": [
    {
      "id": "laptop1",
      "name": "UltraBook Pro",
      "price": 1299.99,
      "categoryRef": "/categories/2",
      "relatedProducts": ["/products/1"]
    },
    {
      "id": "laptop2",
      "name": "DevBook Max",
      "price": 1499.99,
      "categoryRef": "/categories/2",
      "relatedProducts": ["/products/0"]
    }
  ]
}

JSON Type Definition (JTD)

JSON Type Definition (JTD) is an alternative schema language for JSON documents. It was created in response to JSON Schema and is designed to be simpler, focusing on structural and type validation, with a lighter weight vocabulary and fewer constraints.

{
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "uint8" },
    "email": { "type": "string" },
    "isSubscribed": { "type": "boolean" },
    "registrationDate": { "type": "timestamp" }
  },
  "optionalProperties": {
    "phoneNumber": { "type": "string" },
    "address": {
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "country": { "type": "string" }
      },
      "optionalProperties": {
        "postalCode": { "type": "string" }
      }
    },
    "tags": {
      "elements": {
        "type": "string"
      }
    }
  }
}
Example

JSON Schema is the de facto standard for JSON schema, and it is RECOMMENDED for its expressive power and readily-available libraries and tooling. However, JTD is a good alternative for simple use cases, especially where type safety is the primary concern (rather than full schema validation),and it is mentioned here for completeness.