Schema extensions

$$description

The standard defines the description key as having a string value. Since the JSON file format has no provision for some form of line continuation this can result in unwieldy long strings.

To remedy the $$description key is introduced. It can be used with and just like the description key. It accepts an array of strings which it combines into a single string which is then processed just like the description.

This makes it possible to create something like:

{
    ...
    "description": "The usual single string description",
    "$$description": [
        "+------------+------------+-----------+",
        "| Header 1   | Header 2   | Header 3  |",
        "+============+============+===========+",
        "| body row 1 | column 2   | column 3  |",
        "+------------+------------+-----------+",
        "| body row 2 | Cells may span columns.|",
        "+------------+------------+-----------+",
        "| body row 3 | Cells may  | - Cells   |",
        "+------------+ span rows. | - contain |",
        "| body row 4 |            | - blocks. |",
        "+------------+------------+-----------+"
    ],
    ...
}

$$target

After some experimentation I concluded that I needed to extend JSON Schema. Most of the time sphinx-jsonschema just does the ‘sensible’ thing.

The $ref key in JSON Schema posed a problem. It works in conjunction with the id keyword to implement a schema inclusion method.

I wanted to replace the schema inclusion with a hypertext link to the included schema. Working on a number of large schemas I wanted to document the subschemas as type definitions that are being referenced or used by the main schemas. Therefore I wanted to be able to display the subschema on a different documentation page and have the referring document display a clickable link.

In order to implement this I needed to add the $$target key to JSON Schema. $$target takes either a single string or an array of strings as parameter.

The string parameter must match the $ref parameter exactly. So if you are using somewhere the schema:

{
    ...
    "$ref": "#/definitions/sample",
    ...
}

then the definitions section should read:

{
    ...
    "definitions": {
        "sample": {
            "title": "A sample",
            "$$target": "#/definitions/sample"
            ...
        }
    }
}

Note

that $ref and $$target share exactly the same string.

Note

also note the title field in sample. This is required for the reference to work correctly.

When a referenced schema is used from more than one file it is possible that the value of the $ref keywords is not equal.

Consider the case where schemas/service1/sample.json and schemas/service2/sample.json both reference a something subschema located in schemas/service1/referenced.json the objects may look like this in schemas/service1/sample.json:

{
    ...
    "id": "schemas/service1/sample.json",
    "$ref": "referenced.json#/something",
    ...
}

schemas/service2/sample.json would look like:

{
    ...
    "id": "schemas/service2/sample.json",
    "$ref": "../service1/referenced.json#/something",
    ...
}

This is why $target is allowed to have an array of strings as value in referenced.json:

{
    ...
    "title": "Something",
    "$$target": ["referenced.json#/something", "../service1/referenced.json#/something"],
    ...
}

Combining $$target, $ref and documentation files

In order to have $ref entries be displayed as clickable links you need to:

  1. give the referenced schema a title,
  2. give the referenced schema a $$target,
  3. include the referenced schema in the documentation.

The title is needed to create a proper section header for the referenced schema. This section header is used to resolve the link generated by the $ref key. The title is the link label.

The $$target is needed because sphinx-jsonschema does not resolve $ref like a validator using the id key etc. The value of $$target should match the corresponding $ref value exactly. When the schema is referenced from multiple locations using different values for $ref then the value of $$target may be an array of strings instead of a single string.

Finally, the referencing and referenced schemas must both be included explicitly in the documentation. The referenced schema, when part of a larger schema or set of schemas, can be included using json pointer notation.

Example

The file schema.json contains:

{
    "calls": {
        "title": "Allows commercial calls",
        "description": "Person consents to receive commercial offers.",
        "type": "object",
        "properties": {
            "name": {"$ref": "types.json#/Name"},
            "telno": {"$ref": "types.json#/TelephoneNumber"},
            "may_call": {"$ref": "#/definitions/Options"}
        }
    },
    "definitions": {
        "Options": {
            "title": "Options",
            "description": "Embedded definition of type Options",
            "$$target": "#/definitions/Options",
            "type": "string",
            "enum": ["Yes", "No", "Maybe", "Don't care"]
        }
    }
}

The file types.json contains:

{
    "Name": {
        "title": "Name",
        "description": "Someone's first and lastname",
        "$$target": "types.json#/Name",
        "type": "string",
        "maxLength": 80,
    },
    "TelephoneNumber": {
        "title": "Telephone number",
        "description": "Someone's telephone number",
        "$$target": "types.json#/TelephoneNumber",
        "type": "string",
        "pattern": "[0-9]*"
    }
}

The Sphinx source file contains:

Caption
#######

Some blahblah about calling people.

.. jsonschema:: schema.json#/calls

More explanations ...

.. jsonschema:: schema.json#/definitions/Options

Types
~~~~~

Introduction on types.

.. jsonschema:: types.json#/Name

More info on Name.

.. jsonschema:: types.json#/TelephoneNumber

Story about TelephoneNumber construction.

Which would render as:

Caption

Some blahblah about calling people.

Allows commercial calls
Person consents to receive commercial offers.
type object
properties
  • name
Name
  • telno
Telephone number
  • may_call
Options

More explanations …

Options
Embedded definition of type Options
type string
enum Yes, No, Maybe, Don’t care
Types

Introduction on types.

Name
Someone’s first and lastname
type string
maxLength 80

More info on Name.

Telephone number
Someone’s telephone number
type string
pattern [0-9]*

Story about TelephoneNumber construction.