{"id":18310894,"url":"https://github.com/jimschubert/yay","last_synced_at":"2026-03-06T04:33:41.328Z","repository":{"id":199095606,"uuid":"702123070","full_name":"jimschubert/yay","owner":"jimschubert","description":"Working with YAML in Go can be fun.","archived":false,"fork":false,"pushed_at":"2024-09-22T02:53:12.000Z","size":63,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-21T08:35:00.253Z","etag":null,"topics":["go","golang"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/jimschubert/yay","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jimschubert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"jimschubert","patreon":"jimschubert"}},"created_at":"2023-10-08T15:05:26.000Z","updated_at":"2024-09-22T02:53:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"f9dadd8e-9a0e-4ca5-afc4-4da826ed4a96","html_url":"https://github.com/jimschubert/yay","commit_stats":null,"previous_names":["jimschubert/yay"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimschubert%2Fyay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimschubert%2Fyay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimschubert%2Fyay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimschubert%2Fyay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jimschubert","download_url":"https://codeload.github.com/jimschubert/yay/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247383885,"owners_count":20930365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang"],"created_at":"2024-11-05T16:15:48.676Z","updated_at":"2026-03-06T04:33:41.275Z","avatar_url":"https://github.com/jimschubert.png","language":"Go","funding_links":["https://github.com/sponsors/jimschubert","https://patreon.com/jimschubert"],"categories":[],"sub_categories":[],"readme":"# yay\n\nWorking with YAML in Go can be fun. :yay:\n\nThis project provides some utilities to make it slightly more fun by wrapping  [yaml.v3](https://github.com/go-yaml/yaml/tree/v3) and [YAML JSONPath](https://github.com/vmware-labs/yaml-jsonpath/).\n\n\n![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/jimschubert/yay?color=blue\u0026sort=semver)\n![Go Version](https://img.shields.io/github/go-mod/go-version/jimschubert/yay)\n[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue)](./LICENSE)  \n[![build](https://github.com/jimschubert/yay/actions/workflows/build.yml/badge.svg)](https://github.com/jimschubert/yay/actions/workflows/build.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/jimschubert/yay)](https://goreportcard.com/report/github.com/jimschubert/yay)\n\n## Features\n\n* A visitor allowing user defined handlers for standard [yaml.v3](https://github.com/go-yaml/yaml/tree/v3)\n* A [ConditionalHandler](./conditional_handler.go) allowing to define YAML JSONPath preconditions to visitor methods\n\n## Examples\n\n### Standard Handler\n\nFirst, create a handler which satisfies one or more of the interfaces:\n\n* VisitsYaml\n* VisitsDocumentNode\n* VisitsSequenceNode\n* VisitsMappingNode\n* VisitsScalarNode\n* VisitsAliasNode\n\n```go\ntype myHandler struct{}\nfunc (m *myHandler) VisitScalarNode(ctx context.Context, key *yaml.Node, value *yaml.Node) error {\n\tfmt.Printf(\"found key=%s value=%s\\n\", key.Value, value.Value)\n    return nil\n}\n```\n\nThen, pass create a new visitor with this handler and run against the target document node. Error handling omitted from the below example:\n\n```go\ndocument := \u0026yaml.Node{}\n// parse your document\nvisitor, _ := yay.NewVisitor(myHandler{})\n_ = visitor.Visit(context.TODO(), document)\n```\n\n### Conditional Handler\n\nSuppose you have a complex YAML document, and you only want to parse nodes based on some condition. You could use the standard handler and apply those checks on the key/value nodes. \nThis is fine, but may lead to unexpected bugs/behaviors. You can also apply a selector as a precondition using a conditional handler.\n\nConsider this YAML document used in [conditional_handler_test.go](./conditional_handler_test.go):\n\n```yaml\n---\nstore:\n  book:\n  - author: Ernest Hemingway\n    title: The Old Man and the Sea\n  - author: Fyodor Mikhailovich Dostoevsky\n    title: Crime and Punishment\n  - author: Jane Austen\n    title: Sense and Sensibility\n  - author: Kurt Vonnegut Jr.\n    title: Slaughterhouse-Five\n  - author: J. R. R. Tolkien\n    title: The Lord of the Rings\n```\n\nIF you only want to process titles beginning with `S`, you could use the [selector syntax](https://github.com/vmware-labs/yaml-jsonpath#syntax):\n\n```\n$.store.book[?(@.title=~/^S.*$/)]\n```\n\nThis will select each mapping node matching that criteria. Rather than your visitor processing 5 items, you will process 2 items.\nFor example:\n\n```go\ndocument := \u0026yaml.Node{}\n_ = yaml.Unmarshal([]byte(input), document)\n\ncount := 0\nhandler, _ := yay.NewConditionalHandler(\n    yay.OnVisitMappingNode(\"$.store.book[?(@.title=~/^S.*$/)]\",\n        func(ctx context.Context, key *yaml.Node, value *yaml.Node) error {\n            fmt.Printf(\"processed item at index %d\\n\", count)\n            count += 1\n            return nil\n        }))\n\nvisitor, _ := yay.NewVisitor(handler)\n_ = visitor.Visit(context.TODO(), document)\n```\n\nThis will output:\n\n```go\nprocessed item at index 0\nprocessed item at index 1\n```\n\nIf you want to process the item for which your conditional applies, you can continue chaining dot-notation. For example, to process just the scalar `title`:\n\n```go\nhandler, _ := yay.NewConditionalHandler(\n    yay.OnVisitScalarNode(\"$.store.book[?(@.title=~/^S.*$/)].title\",\n        func(ctx context.Context, key *yaml.Node, value *yaml.Node) error {\n            fmt.Printf(\"processed item at index %d\\n\", count)\n            count += 1\n            return nil\n        }))\n```\n\nNotice the use of the functional `OnVisitScalarNode` and the matcher is now `$.store.book[?(@.title=~/^S.*$/)].title`.\n\n\n## Caveats\n\nNote that `key` may be nil if the node type you're processing exists within a sequence in the original document. That is, items within sequences don't have keys.\n\n## Install\n\n```\ngo get -u github.com/jimschubert/yay\n```\n\n## Build/Test\n\n```shell\ngo test -v -race -cover ./...\n```\n\n## License\n\nThis project is [licensed](./LICENSE) under Apache 2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimschubert%2Fyay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjimschubert%2Fyay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimschubert%2Fyay/lists"}