mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
64 lines
3.5 KiB
Markdown
64 lines
3.5 KiB
Markdown
|
---
|
||
|
title: "Writing JSON Schemas"
|
||
|
slug: "writing-json-schemas"
|
||
|
hidden: false
|
||
|
createdAt: "2023-01-25T05:46:43.718Z"
|
||
|
updatedAt: "2023-01-30T15:36:28.523Z"
|
||
|
---
|
||
|
A JSON Schema is a JSON file which defines what a structure should look like; in our case we use it in our testsuite to check that they match command responses, and also use it to generate our documentation.
|
||
|
|
||
|
Yes, schemas are horrible to write, but they're damn useful. We can only use a subset of the full [JSON Schema Specification](https://json-schema.org/), but if you find that limiting it's probably a sign that you should simplify your JSON output.
|
||
|
|
||
|
## Updating a Schema
|
||
|
|
||
|
If you add a field, you should add it to the schema, and you must add "added": "VERSION" (where VERSION is the next release version!).
|
||
|
|
||
|
Similarly, if you deprecate a field, add "deprecated": "VERSION" (where VERSION is the next release version). They will be removed two versions later.
|
||
|
|
||
|
## How to Write a Schema
|
||
|
|
||
|
Name the schema doc/schemas/`command`.schema.json: the testsuite should pick it up and check all invocations of that command against it.
|
||
|
|
||
|
I recommend copying an existing one to start.
|
||
|
|
||
|
You will need to put the magic lines in the manual page so `make doc-all` will fill it in for you:
|
||
|
|
||
|
```json
|
||
|
[comment]: # (GENERATE-FROM-SCHEMA-START)
|
||
|
[comment]: # (GENERATE-FROM-SCHEMA-END)
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
If something goes wrong, try tools/fromscheme.py doc/schemas/`command`.schema.json to see how far it got before it died.
|
||
|
|
||
|
You should always use `"additionalProperties": false`, otherwise your schema might not be covering everything. Deprecated fields simply have `"deprecated": true` in their properties, so they are allowed by omitted from the documentation.
|
||
|
|
||
|
You should always list all fields which are _always_ present in `"required"`.
|
||
|
|
||
|
We extend the basic types; see [fixtures.py](https://github.com/ElementsProject/lightning/tree/master/contrib/pyln-testing/pyln/testing/fixtures.py).
|
||
|
|
||
|
In addition, before committing a new schema or a new version of it, make sure that it is well formatted. If you don't want do it by hand, use `make fmt-schema` that uses jq under the hood.
|
||
|
|
||
|
### Using Conditional Fields
|
||
|
|
||
|
Sometimes one field is only sometimes present; if you can, you should make the schema know when it should (and should not!) be there.
|
||
|
|
||
|
There are two kinds of conditional fields expressable: fields which are only present if another field is present, or fields only present if another field has certain values.
|
||
|
|
||
|
To add conditional fields:
|
||
|
|
||
|
1. Do _not_ mention them in the main "properties" section.
|
||
|
2. Set `"additionalProperties": true` for the main "properties" section.
|
||
|
3. Add an `"allOf": [` array at the same height as `"properties"'`. Inside this place one `if`/`then` for each conditional field.
|
||
|
4. If a field simply requires another field to be present, use the pattern `"required": [ "field" ]` inside the "if".
|
||
|
5. If a field requires another field value, use the pattern
|
||
|
`"properties": { "field": { "enum": [ "val1", "val2" ] } }` inside the "if".
|
||
|
6. Inside the "then", use `"additionalProperties": false` and place empty `{}` for all the other possible properties.
|
||
|
7. If you haven't covered all the possibilties with `if` statements, add an `else` with `"additionalProperties": false` which simply mentions every allowable property. This ensures that the fields can _only_ be present when conditions are met.
|
||
|
|
||
|
### JSON Drinking Game!
|
||
|
|
||
|
1. Sip whenever you have an additional comma at the end of a sequence.
|
||
|
2. Sip whenever you omit a comma in a sequence because you cut & paste.
|
||
|
3. Skull whenever you wish JSON had comments.
|