https://github.com/bitwizeshift/go-yamlpath
https://github.com/bitwizeshift/go-yamlpath
Last synced: 17 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/bitwizeshift/go-yamlpath
- Owner: bitwizeshift
- License: apache-2.0
- Created: 2024-12-26T15:37:04.000Z (about 1 year ago)
- Default Branch: master
- Last Pushed: 2025-01-04T04:23:23.000Z (about 1 year ago)
- Last Synced: 2025-03-09T19:42:58.447Z (10 months ago)
- Language: Go
- Size: 271 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# YAMLPath
[](https://github.com/bitwizeshift/go-yamlpath/actions/workflows/build-and-test.yaml)
[](https://godoc.org/rodusek.dev/pkg/yamlpath)
[](https://goreportcard.com/report/rodusek.dev/pkg/yamlpath)
A fluent and powerful YAML query language that can be embedded into any Go
library or application.
This language takes heavy inspiration from the [JSONPath] query language, but
features changes to the specification that simplify traversal and make the
language more fluent and readable.
This is built on top of the [`gopkg.in/yaml.v3`] library in Go by querying
[`*yaml.Node`] objects directly. This allows for preserving source-location
information -- which is powerful for providing diagnostics and error messages
when validating YAML documents.
[JSONPath]: https://goessner.net/articles/JsonPath/
[`gopkg.in/yaml.v3`]: https://gopkg.in/yaml.v3
## Quickstart
* [๐ฆ Installation](#installation)
* [๐งพ Features](#features)
* [๐ Example Use](#example-use)
* [๐ Documentation](./docs/index.md)
* [๐ Grammar](./data/yamlpath.g4)
* [๐ Extensions](./docs/extensions.md)
* [โ FAQ](./docs/faq.md)
* โ๏ธ [MIT](./LICENSE-MIT) or [APACHE-2](./LICENSE-APACHE)
## Installation
To install the package, use the following `go get` command:
```sh
go get rodusek.dev/pkg/yamlpath
```
## Features
This library has full feature-parity with JSONPath, although not all features
are provided in the same way. The follow features are supported:
* โ
Root and Current node selection with `$` and `@`[^1]
* โ
Child node selection with `.`
* โ
Recursive descent with `descendants()` [^2]
* โ
Array index selection with `[]`[^3]
* โ
Array slice selection with `[::]`
* โ
Union of multiple selections with ` | `
* โ
Filtering with the `where` function, e.g. `$.people.where(name == "bitwizeshift")`
* โ
Comparison operators with `==`, `!=`, `<`, `>`, `<=`, `>=`
* โ
Containment operators with `in`, `nin`, `subsetof` (e.g. `age in [1, 2, 3]`)
* โ
Regular expression operator with `=~` (e.g. `name =~ /^b.*shift$/i`)
* โ
Logical expression operator with `&&`, `||`
* โ
Arithmetic operators with `+`, `-`, `*`, `/`, `%`
* โ
String concatenation with `key + "string"`
* โ
Function support (including custom user-defined functions!)
* โ
Dynamic subexpressions; any expression can be used as inputs to functions[^4]
* โ
External constants that can be provided at compile-time
[^1]: These are optional in YAMLPath definitions. The path is always assumed to
be the "current" context path if unspecified; but can be provided for
disambiguation.
[^2]: The `descendants()` function provides feature-parity with JSONPath's
recursive descent operator `..`. This is a more explicit way to select
descendants, and is more readable.
[^3]: In YAMLPath, only indices are selected with the index operator. Fields are
selected with the `.` operator. To select fields with a string value, the
`select` function may be used (e.g. `$.select("some key")`).
[^4]: Dynamic subexpressions along with external constants provide rough
feature-parity with JSONPath's "script" functinality, since it enables the
calling language to provide data dynamically to YAMLPath expressions.
## Example Use
> [!NOTE]
> For more examples, see the [examples](./_examples) directory.
This illustrates a simple example using this library to validate configurations,
with output diagnostics appearing in GitHub annotation format. This validates
some criteria on a `book` yaml object:
```go
path := yamlpath.MustCompile("store.book.where(price < 10.00)")
filepath := "bookstore.yaml" // Some filepath to the YAML file
file, err := os.Open(filepath) // some file handle to the YAML file
if err != nil {
log.Fatal(err)
}
defer file.Close()
var node yaml.Node
if err := yaml.NewDecoder(file).Decode(&node); err != nil {
log.Fatal(err)
}
result, err := path.Match(&node)
if err != nil {
log.Fatal(err)
}
for _, node := range result {
if err := validateBook(result); err != nil {
// This is in GitHub annotation format
fmt.Println("::error file=%s,line=%d,title=Book validation failed::%v",
filepath,
result.Line,
err,
)
}
}
```