Lidy is:
- The Lidy schema-type language, a YAML language to specify how to check YAML files
- An engine to run the Lidy schema on YAML files
- A rich deserialisation tool (if you want it to)
Currently, the Lidy project is available in two languages:
- Javascript, in the repository lidy-js
- Golang, in the repository lidy-go (this repository)
Both implementations fully adhere to the specification described in the documentation.
However, the way to invoke the parsers currently differs between the two implementations:
- lidy-go uses the concept of builder (see the specific documentation)
- lidy-js uses a similar interface (and in particular the principle of listeners) to that offered by the antlr tool.
- Content
- JSON schema
- Example
- Alternatives: YAML Schema validators
- Using Regex
- Documentation
- Short reference
- Not yet in Lidy
- Contributing
What's the point of Lidy, when there's already JSON schema?
- YAML: Lidy targets YAML rather than JSON. Of course, it does work with JSON perfectly fine.
- Refs: In Lidy, refs are first class citizens, they are just like in programming languages:
<name>, as opposed to JSON Schema's heavy{ ref: "#/<name>" }, see below. - Line numbers: Lidy is meant to assist your users with writing YAML: Lidy provides the line numbers at which the checking failed.
- Algebriac data types: Lidy schema are similar to Algebriac data types. They have union types (
_oneOf), positional product types (_list), named product types (_map), and combined types (_merge). (N.B. parameterized types aren't yet there, but they are on our short list). - Rich deserialisation: Lidy provides support for rich deserialisation. It is a core use-case. This includes access to the source line numbers.
- Custom checkers: Writing a custom value checker is also a core use-case. Actually, it's just as easy as writing a type deserialiser since Lidy handles the two through the same interface.
- Language Recognition: Lidy is a lexical and grammar parser that can build and walk parse trees. It is completely equivalent to a tool like antlr, but for YAML-based DSLs, given that antlr is unable to parse languages built on top of YAML.
Where you used to write "a": { "ref": "#/$def/b" }, in JSON schema, you now write "a": "b", which is much shorter. Lidy does not support accessing non-root nodes. All nodes that must be referred to must be at the root of the Lidy schema.
Note: Lidy does not yet support remote references.
main.go
package main
import (
"fmt"
"github.com/ditrit/lidy"
)
func main() {
result, errorList := lidy.NewParser(
"treeDefinition.yaml",
[]byte(`
main: tree
tree:
_map:
name: string
children:
_listOf: tree
`),
).Parse(
lidy.NewFile(
"treeContent.yaml",
[]byte(`
name: root
children:
- name: leafA
children: []
- name: branchB
children:
- name: leafC
children: []
- name: leafD
children: []
`),
),
)
if len(errorList) > 0 {
panic(errorList[0])
}
mapResult := result.(lidy.MapResult)
fmt.Println(mapResult)
}Here's a list of schema validators we could find:
- Kwalify, [source (mirror?)], [website] (Ruby and Java, v0.7.2, 2010-07-18)
- pykwalify [source], [documentation] (Python, v1.7.0, 2018-08-03)
- Rx [source], [website] (Js, Perl, PHP, Python, Ruby, v0.200006, 2014-05-21)
Also see the dedicated page on JSON Schema Everywhere.
And a few more project(s):
- Azuki [source], just a Map evaluation tool (Java)
None has the feature-set of Lidy, nor its type-oriented approach.
If you need a regex to match a well-known format, think of going shopping for it before you start writing it. Ressources: RgxDB, Regex101.
See DOCUMENTATION.md
- Expression
- A lidy expression specifies a way to check a yaml value
- Rule
- A user rule declaration gives a rule name to an expression
- Builder
- A builder is a user-provided function which can process the data read by a rule, and change its content, or produce an error
- Scalar type
- Scalar types are predefined lidy rules which allow to check for a given scalar type, i.e. a type that is not a container
- Container checker
- A container checker allows to create a lidy expression for a YAML map or a YAML sequence matching certain types
A lidy expression is either:
- The name of a predefined lidy rule
- The name of a lidy rule defined in the same document
- A YAML map which associates one or more lidy keywords to its YAML argument. See Lidy checker forms.
- Note: Not all keyword combinations are valid
Also see lidy expression.
Also see predefined lidy rules.
booleanfloatint-- integerstringnullType-- null
Also see Scalar rules.
timestamp-- ISO 8601 datetimebinary-- a base64 encoded binary blob, with space characters allowed
Also see Predefined string checker rules.
any,anyData-- any yaml structure. See any
The difference between any and anyData is in how they process the yaml structure that they match. any simply ignores the data and produces a result whose data is null (nil or null or None), while anyData processes the yaml structure it matches into a tree of Result elements.
- The
neverpredefined rule never matches anything. It is used to produce an error when a rule is applied to a value that should never be encountered.
_map-- followed by a map of exact keys to lidy expressions_mapOf-- Example:_mapOf: { string: int }_merge-- create a map checker merging the keys of the listed map checkers_mapFacultative-- like_map, but the specified entries aren't mendatory
_list-- (the equivalent of_mapbut for sequences. It could have been named_seq)_listOf_listFacultative
_oneOf-- accept a list of lidy expressions and select the first that matches, or fail
_nb-- the container must exactly have the specified number of entries_max-- the container must have at most the specified number of entries_min-- the container must have at least the specified number of entries
_regex-- applies only to strings. Accepted syntax at https://github.com/google/re2/wiki/Syntax_in-- an exact enumeration of terminal YAML values the value must be part of_range-- a range over integers or floats with inclusive or exclusive boundaries
Declare a parameter type name:
<ContentType>: []
# the <> are forbidden in lidy identifiers. This form is detected as a
# parameter type name declarationDeclare a functional type:
tree<ContentType>:
_map:
name: string
children: treeChildren
# treeChildren requires a parameter: `treeChildren<ContentType>`
# but lidy is smart enougth to pass it from the parent automatically, since they
# uses the same type name
treeChildren<ContentType>:
_listOf: treeOrContent
treeOrContent<ContentType>:
_oneOf:
- tree
- ContentTypeRefer to the functional type:
main: tree<boolean>If you have any idea that you'd like to see added to Lidy, please create an issue in the issue tracker to share your feature request with us (remember to search-check for duplicate issues first).
You're also welcome to report bugs, ask questions or use the issue tracker as you see fit. We try to be welcoming.
Cloning:
git clone https://github.com/ditrit/lidy
cd lidyRunning Lidy's go tests:
cd go/lidy; go test