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: .. code-block:: rst { ... "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: Caption ####### Some blahblah about calling people. .. sidebar:: Benefits This method lets you arrange the schema parts to match the structure of your documentation and also allows you to create multiple copies of a schema in your documentation. .. jsonschema:: #/calls { "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"] } } } More explanations ... .. jsonschema:: #/definitions/Options { "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"] } } } Types ~~~~~ Introduction on types. .. jsonschema:: #/Name { "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]*" } } More info on Name. .. jsonschema:: #/TelephoneNumber { "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]*" } } Story about TelephoneNumber construction.