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:
- give the referenced schema a title,
- give the referenced schema a $$target,
- 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: