mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
doc: document how to try to write JSON schemas.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -194,6 +194,12 @@ All `warning` fields should have unique names which start with
|
|||||||
`warning_`, the value of which should be an explanation. This allows
|
`warning_`, the value of which should be an explanation. This allows
|
||||||
for programs to deal with them sanely, and also perform translations.
|
for programs to deal with them sanely, and also perform translations.
|
||||||
|
|
||||||
|
### Documenting JSON APIs
|
||||||
|
|
||||||
|
We use JSON schemas to validate that JSON-RPC returns are in the
|
||||||
|
correct form, and also to generate documentation. See
|
||||||
|
[doc/schemas/WRITING_SCHEMAS.md](WRITING_SCHEMAS.md).
|
||||||
|
|
||||||
## Changing JSON APIs
|
## Changing JSON APIs
|
||||||
|
|
||||||
All JSON API changes need a Changelog line (see below).
|
All JSON API changes need a Changelog line (see below).
|
||||||
|
|||||||
77
doc/schemas/WRITING_SCHEMAS.md
Normal file
77
doc/schemas/WRITING_SCHEMAS.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Writing JSON Schemas
|
||||||
|
|
||||||
|
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 [https://json-schema.org/](JSON Schema
|
||||||
|
Specification), but if you find that limiting it's probably a sign
|
||||||
|
that you should simplify your JSON output.
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
```
|
||||||
|
[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
|
||||||
|
[contrib/pyln-testing/pyln/testing/fixtures.py](fixtures.py).
|
||||||
|
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
Good luck!
|
||||||
|
Rusty.
|
||||||
Reference in New Issue
Block a user