{"id":13397047,"url":"https://github.com/spyzhov/ajson","last_synced_at":"2026-01-18T02:41:00.493Z","repository":{"id":38420398,"uuid":"174417748","full_name":"spyzhov/ajson","owner":"spyzhov","description":"Abstract JSON for Golang with JSONPath support ","archived":false,"fork":false,"pushed_at":"2024-06-14T06:43:09.000Z","size":312,"stargazers_count":224,"open_issues_count":14,"forks_count":22,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-07-31T18:18:59.939Z","etag":null,"topics":["golang","golang-package","json","json-parser","jsonpath"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spyzhov.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,"publiccode":null,"codemeta":null},"funding":{"custom":["https://paypal.me/StepanPyzhov"]}},"created_at":"2019-03-07T20:47:38.000Z","updated_at":"2024-07-12T13:22:17.000Z","dependencies_parsed_at":"2024-06-18T12:59:16.221Z","dependency_job_id":null,"html_url":"https://github.com/spyzhov/ajson","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/spyzhov/ajson","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spyzhov%2Fajson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spyzhov%2Fajson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spyzhov%2Fajson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spyzhov%2Fajson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spyzhov","download_url":"https://codeload.github.com/spyzhov/ajson/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spyzhov%2Fajson/sbom","scorecard":{"id":842955,"data":{"date":"2025-08-11","repo":{"name":"github.com/spyzhov/ajson","commit":"1f0ecf9280c56ba64e5ce1883d90594ef588e751"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Code-Review","score":1,"reason":"Found 3/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:74: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/spyzhov/ajson/main.yml/master?enable=pin","Warn: goCommand not pinned by hash: .github/workflows/main.yml:56","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   1 out of   2 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:29","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.9.6 not signed: https://api.github.com/repos/spyzhov/ajson/releases/187420613","Warn: release artifact v0.9.5 not signed: https://api.github.com/repos/spyzhov/ajson/releases/181226441","Warn: release artifact v0.9.4 not signed: https://api.github.com/repos/spyzhov/ajson/releases/173157945","Warn: release artifact v0.9.3 not signed: https://api.github.com/repos/spyzhov/ajson/releases/160427201","Warn: release artifact v0.9.2 not signed: https://api.github.com/repos/spyzhov/ajson/releases/160268982","Warn: release artifact v0.9.6 does not have provenance: https://api.github.com/repos/spyzhov/ajson/releases/187420613","Warn: release artifact v0.9.5 does not have provenance: https://api.github.com/repos/spyzhov/ajson/releases/181226441","Warn: release artifact v0.9.4 does not have provenance: https://api.github.com/repos/spyzhov/ajson/releases/173157945","Warn: release artifact v0.9.3 does not have provenance: https://api.github.com/repos/spyzhov/ajson/releases/160427201","Warn: release artifact v0.9.2 does not have provenance: https://api.github.com/repos/spyzhov/ajson/releases/160268982"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 3 commits out of 24 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T20:52:05.845Z","repository_id":38420398,"created_at":"2025-08-23T20:52:05.846Z","updated_at":"2025-08-23T20:52:05.846Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28526679,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["golang","golang-package","json","json-parser","jsonpath"],"created_at":"2024-07-30T18:01:10.147Z","updated_at":"2026-01-18T02:41:00.451Z","avatar_url":"https://github.com/spyzhov.png","language":"Go","funding_links":["https://paypal.me/StepanPyzhov"],"categories":["Go","JSON","Relational Databases"],"sub_categories":["Advanced Console UIs","Search and Analytic Databases","SQL 查询语句构建库","检索及分析资料库"],"readme":"# Abstract JSON \n\n[![Build](https://github.com/spyzhov/ajson/actions/workflows/main.yml/badge.svg)](https://github.com/spyzhov/ajson/actions/workflows/main.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/spyzhov/ajson)](https://goreportcard.com/report/github.com/spyzhov/ajson)\n[![GoDoc](https://godoc.org/github.com/spyzhov/ajson?status.svg)](https://godoc.org/github.com/spyzhov/ajson)\n[![codecov](https://codecov.io/gh/spyzhov/ajson/branch/master/graph/badge.svg)](https://codecov.io/gh/spyzhov/ajson)\n[![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/avelino/awesome-go#json)\n\nAbstract [JSON](https://www.json.org/) is a small golang package provides a parser for JSON with support of JSONPath, in case when you are not sure in its structure.\n\nMethod `Unmarshal` will scan all the byte slice to create a root node of JSON structure, with all its behaviors.\n\nMethod `Marshal` will serialize current `Node` object to JSON structure.\n\nEach `Node` has its own type and calculated value, which will be calculated on demand. \nCalculated value saves in `atomic.Value`, so it's thread safe.\n\nMethod `JSONPath` will returns slice of found elements in current JSON data, by [JSONPath](http://goessner.net/articles/JsonPath/) request.\n\n## Compare with other solutions\n\nCheck the [cburgmer/json-path-comparison](https://cburgmer.github.io/json-path-comparison/) project.\n\n# Usage\n\n[Playground](https://play.golang.com/p/iIxkktxN0SK)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`...`)\n\n\troot, _ := ajson.Unmarshal(json)\n\tnodes, _ := root.JSONPath(\"$..price\")\n\tfor _, node := range nodes {\n\t\tnode.SetNumeric(node.MustNumeric() * 1.25)\n\t\tnode.Parent().AppendObject(\"currency\", ajson.StringNode(\"\", \"EUR\"))\n\t}\n\tresult, _ := ajson.Marshal(root)\n\n\tfmt.Printf(\"%s\", result)\n}\n```\n\n# Console application\n\nYou can download `ajson` cli from the [release page](https://github.com/spyzhov/ajson/releases), or install from the source:\n\n```shell script\ngo get github.com/spyzhov/ajson/cmd/ajson@v0.9.6\n```\n\nUsage:\n\n```\nUsage: ajson [-mq] \"jsonpath\" [\"input\"]\n  Read JSON and evaluate it with JSONPath.\nParameters:\n  -m, --multiline  Input file/stream will be read as a multiline JSON. Each line should have a full valid JSON.\n  -q, --quiet      Do not print errors into the STDERR.\nArgument:\n  jsonpath         Valid JSONPath or evaluate string (Examples: \"$..[?(@.price)]\", \"$..price\", \"avg($..price)\")\n  input            Path to the JSON file. Leave it blank to use STDIN.\n```\n\nExamples:\n\n```shell script\n  ajson \"avg($..registered.age)\" \"https://randomuser.me/api/?results=5000\"\n  ajson \"$.results.*.name\" \"https://randomuser.me/api/?results=10\"\n  curl -s \"https://randomuser.me/api/?results=10\" | ajson \"$..coordinates\"\n  ajson \"$\" example.json\n  echo \"3\" | ajson \"2 * pi * $\"\n  docker logs image-name -f | ajson -qm 'root($[?(@==\"ERROR\" \u0026\u0026 key(@)==\"severity\")])'\n```\n\n# JSONPath\n\nCurrent package supports JSONPath selection described at [http://goessner.net/articles/JsonPath/](http://goessner.net/articles/JsonPath/).\n\nJSONPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination with an XML document. \nSince a JSON structure is usually anonymous and doesn't necessarily have a \"root member object\" JSONPath assumes the abstract name $ assigned to the outer level object.\n\nJSONPath expressions can use the dot–notation\n\n`$.store.book[0].title`\n\nor the bracket–notation\n\n`$['store']['book'][0]['title']`\n\nfor input paths. Internal or output paths will always be converted to the more general bracket–notation.\n\nJSONPath allows the wildcard symbol `*` for member names and array indices. \nIt borrows the descendant operator `..` from E4X and the array slice syntax proposal `[start:end:step]` from ECMASCRIPT 4.\n\nExpressions of the underlying scripting language `(\u003cexpr\u003e)` can be used as an alternative to explicit names or indices as in\n\n`$.store.book[(@.length-1)].title`\n\nusing the symbol `@` for the current object. Filter expressions are supported via the syntax `?(\u003cboolean expr\u003e)` as in\n\n`$.store.book[?(@.price \u003c 10)].title`\n\nHere is a complete overview and a side by side comparison of the JSONPath syntax elements with its XPath counterparts.\n\n| JSONPath | Description |\n|----------|---|\n| `$`      | the root object/element |\n| `@`      | the current object/element |\n| `.` or `[]` | child operator |\n| `..`     | recursive descent. JSONPath borrows this syntax from E4X. |\n| `*`      | wildcard. All objects/elements regardless their names. |\n| `[]`     | subscript operator. XPath uses it to iterate over element collections and for predicates. In Javascript and JSON it is the native array operator. |\n| `[,]`    | Union operator in XPath results in a combination of node sets. JSONPath allows alternate names or array indices as a set. |\n| `[start:end:step]` | array slice operator borrowed from ES4. |\n| `?()`    | applies a filter (script) expression. |\n| `()`     | script expression, using the underlying script engine. |\n\n## Script engine\n\n### Predefined constant\n\nPackage has several predefined constants. \n\n     e       math.E     float64\n     pi      math.Pi    float64\n     phi     math.Phi   float64\n     \n     sqrt2     math.Sqrt2   float64\n     sqrte     math.SqrtE   float64\n     sqrtpi    math.SqrtPi  float64\n     sqrtphi   math.SqrtPhi float64\n     \n     ln2     math.Ln2    float64\n     log2e   math.Log2E  float64\n     ln10    math.Ln10   float64\n     log10e  math.Log10E float64\n          \n     true    true       bool\n     false   false      bool\n     null    nil        interface{}\n     \nYou are free to add new one with function `AddConstant`:\n\n```go\n    AddConstant(\"c\", NumericNode(\"speed of light in vacuum\", 299_792_458))\n```\n\n#### Examples\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing `true` in path\u003c/summary\u003e\n\n[Playground](https://play.golang.org/p/h0oFLaE11Tn)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`{\"foo\": [true, null, false, 1, \"bar\", true, 1e3], \"bar\": [true, \"baz\", false]}`)\n\tresult, _ := ajson.JSONPath(json, `$..[?(@ == true)]`)\n\tfmt.Printf(\"Count of `true` values: %d\", len(result))\n}\n```\nOutput:\n```\nCount of `true` values: 3\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eUsing `null` in eval\u003c/summary\u003e\n\n[Playground](https://play.golang.org/p/wpqh1Fw5vWE)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`{\"foo\": [true, null, false, 1, \"bar\", true, 1e3], \"bar\": [true, \"baz\", false]}`)\n\tresult, _ := ajson.JSONPath(json, `$..[?(@ == true)]`)\n\tfmt.Printf(\"Count of `true` values: %d\", len(result))\n}\n```\nOutput:\n```\nCount of `true` values: 3\n```\n\u003c/details\u003e\n\n### Supported operations\n\nPackage has several predefined operators.\n\n[Operator precedence](https://golang.org/ref/spec#Operator_precedence)\n\n\tPrecedence    Operator\n\t    6\t    \t  **\n\t    5             *  /  %  \u003c\u003c  \u003e\u003e  \u0026  \u0026^\n\t    4             +  -  |  ^\n\t    3             ==  !=  \u003c  \u003c=  \u003e  \u003e= =~\n\t    2             \u0026\u0026\n\t    1             ||\n\n[Arithmetic operators](https://golang.org/ref/spec#Arithmetic_operators)\n\n\t**   power                  integers, floats\n\t+    sum                    integers, floats, strings\n\t-    difference             integers, floats\n\t*    product                integers, floats\n\t/    quotient               integers, floats\n\t%    remainder              integers\n\n\t\u0026    bitwise AND            integers\n\t|    bitwise OR             integers\n\t^    bitwise XOR            integers\n\t\u0026^   bit clear (AND NOT)    integers\n\n\t\u003c\u003c   left shift             integer \u003c\u003c unsigned integer\n\t\u003e\u003e   right shift            integer \u003e\u003e unsigned integer\n\n\t==  equals                  any\n\t!=  not equals              any\n\t\u003c   less                    any\n\t\u003c=  less or equals          any\n\t\u003e   larger                  any\n\t\u003e=  larger or equals        any\n\t=~  equals regex string     strings\n\nYou are free to add new one with function `AddOperation`:\n\n```go\n\tAddOperation(\"\u003c\u003e\", 3, false, func(left *ajson.Node, right *ajson.Node) (node *ajson.Node, err error) {\n\t\tresult, err := left.Eq(right)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn BoolNode(\"neq\", !result), nil\n\t})\n```\n\n#### Examples\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing `regex` operator\u003c/summary\u003e\n\n[Playground](https://play.golang.org/p/Lm_F4OGTMWl)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`[{\"name\":\"Foo\",\"mail\":\"foo@example.com\"},{\"name\":\"bar\",\"mail\":\"bar@example.org\"}]`)\n\tresult, err := ajson.JSONPath(json, `$.[?(@.mail =~ '.+@example\\\\.com')]`)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"JSON: %s\", result[0].Source())\n\t// Output:\n\t// JSON: {\"name\":\"Foo\",\"mail\":\"foo@example.com\"}\n}\n\n```\nOutput:\n```\nJSON: {\"name\":\"Foo\",\"mail\":\"foo@example.com\"}\n```\n\u003c/details\u003e\n\n### Supported functions\n\nPackage has several predefined functions.\n\n    abs          math.Abs           integers, floats\n    acos         math.Acos          integers, floats\n    acosh        math.Acosh         integers, floats\n    asin         math.Asin          integers, floats\n    asinh        math.Asinh         integers, floats\n    atan         math.Atan          integers, floats\n    atanh        math.Atanh         integers, floats\n    avg          Average            array of integers or floats\n    b64decode    b64 Decoding       string\n    b64encode    b64 Encoding       string \n    b64encoden   b64 Encoding (no padding)    string\n    cbrt         math.Cbrt          integers, floats\n    ceil         math.Ceil          integers, floats\n    cos          math.Cos           integers, floats\n    cosh         math.Cosh          integers, floats\n    erf          math.Erf           integers, floats\n    erfc         math.Erfc          integers, floats\n    erfcinv      math.Erfcinv       integers, floats\n    erfinv       math.Erfinv        integers, floats\n    exp          math.Exp           integers, floats\n    exp2         math.Exp2          integers, floats\n    expm1        math.Expm1         integers, floats\n    factorial    N!                 unsigned integer\n    first        Get first element  any\n    floor        math.Floor         integers, floats\n    gamma        math.Gamma         integers, floats\n    is_array     Is type Array      any\n    is_bool      Is type Bool       any\n    is_float     Is type Float      any\n    is_int       Is type Int        any\n    is_null      Is type Null       any\n    is_numeric   Is type Numeric    any\n    is_object    Is type Object     any\n    is_string    Is type String     any\n    is_uint      Is type Uint       any\n    j0           math.J0            integers, floats\n    j1           math.J1            integers, floats\n    key          Key of element     string\n    last         Get last element   any\n    length       Length of array    array, string\n    log          math.Log           integers, floats\n    log10        math.Log10         integers, floats\n    log1p        math.Log1p         integers, floats\n    log2         math.Log2          integers, floats\n    logb         math.Logb          integers, floats\n    not          not                any\n    parent       Get parent element any\n    pow10        math.Pow10         integer\n    rand         N*rand.Float64     float\n    randint      rand.Intn          integer\n    root         Get root element   any\n    round        math.Round         integers, floats\n    roundtoeven  math.RoundToEven   integers, floats\n    sin          math.Sin           integers, floats\n    sinh         math.Sinh          integers, floats\n    size         Count of elements  array, object\n    sum          Sum                array of integers or floats\n    sqrt         math.Sqrt          integers, floats\n    tan          math.Tan           integers, floats\n    tanh         math.Tanh          integers, floats\n    trunc        math.Trunc         integers, floats\n    y0           math.Y0            integers, floats\n    y1           math.Y1            integers, floats\n\nYou are free to add new one with function `AddFunction`:\n\n```go\n\tAddFunction(\"trim\", func(node *ajson.Node) (result *Node, err error) {\n\t\tif node.IsString() {\n\t\t\treturn StringNode(\"trim\", strings.TrimSpace(node.MustString())), nil\n\t\t}\n\t\treturn\n\t})\n```\n\n#### Examples\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing `avg` for array\u003c/summary\u003e\n\n[Playground](https://play.golang.org/p/cM66hTE-CX1)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`{\"prices\": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}`)\n\troot, err := ajson.Unmarshal(json)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tresult, err := ajson.Eval(root, `avg($.prices)`)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Avg price: %0.1f\", result.MustNumeric())\n\t// Output:\n\t// Avg price: 5.5\n}\n```\nOutput:\n```\nAvg price: 5.5\n```\n\u003c/details\u003e\n\n# Examples\n\nCalculating `AVG(price)` when object is heterogeneous.\n\n```json\n{\n  \"store\": {\n    \"book\": [\n      {\n        \"category\": \"reference\",\n        \"author\": \"Nigel Rees\",\n        \"title\": \"Sayings of the Century\",\n        \"price\": 8.95\n      },\n      {\n        \"category\": \"fiction\",\n        \"author\": \"Evelyn Waugh\",\n        \"title\": \"Sword of Honour\",\n        \"price\": 12.99\n      },\n      {\n        \"category\": \"fiction\",\n        \"author\": \"Herman Melville\",\n        \"title\": \"Moby Dick\",\n        \"isbn\": \"0-553-21311-3\",\n        \"price\": 8.99\n      },\n      {\n        \"category\": \"fiction\",\n        \"author\": \"J. R. R. Tolkien\",\n        \"title\": \"The Lord of the Rings\",\n        \"isbn\": \"0-395-19395-8\",\n        \"price\": 22.99\n      }\n    ],\n    \"bicycle\": {\n      \"color\": \"red\",\n      \"price\": 19.95\n    },\n    \"tools\": null\n  }\n}\n```\n\n## Unmarshal\n\n[Playground](https://play.golang.org/p/xny93dzjZCK)\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tdata := []byte(`{\"store\": {\"book\": [\n{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, \n{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, \n{\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, \n{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}], \n\"bicycle\": {\"color\": \"red\", \"price\": 19.95}, \"tools\": null}}`)\n\n\troot, err := ajson.Unmarshal(data)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tstore := root.MustKey(\"store\").MustObject()\n\n\tvar prices float64\n\tsize := 0\n\tfor _, objects := range store {\n\t\tif objects.IsArray() \u0026\u0026 objects.Size() \u003e 0 {\n\t\t\tsize += objects.Size()\n\t\t\tfor _, object := range objects.MustArray() {\n\t\t\t\tprices += object.MustKey(\"price\").MustNumeric()\n\t\t\t}\n\t\t} else if objects.IsObject() \u0026\u0026 objects.HasKey(\"price\") {\n\t\t\tsize++\n\t\t\tprices += objects.MustKey(\"price\").MustNumeric()\n\t\t}\n\t}\n\n\tif size \u003e 0 {\n\t\tfmt.Println(\"AVG price:\", prices/float64(size))\n\t} else {\n\t\tfmt.Println(\"AVG price:\", 0)\n\t}\n}\n```\n\n## JSONPath:\n\n[Playground](https://play.golang.org/p/7twZHOd6dbT)\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tdata := []byte(`{\"store\": {\"book\": [\n{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, \n{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, \n{\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, \n{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}], \n\"bicycle\": {\"color\": \"red\", \"price\": 19.95}, \"tools\": null}}`)\n\n\tnodes, err := ajson.JSONPath(data, \"$..price\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tvar prices float64\n\tsize := len(nodes)\n\tfor _, node := range nodes {\n\t\tprices += node.MustNumeric()\n\t}\n\n\tif size \u003e 0 {\n\t\tfmt.Println(\"AVG price:\", prices/float64(size))\n\t} else {\n\t\tfmt.Println(\"AVG price:\", 0)\n\t}\n}\n```\n\n## Eval\n\n[Playground](https://play.golang.org/p/lTXnlRU3sgR)\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`{\"store\": {\"book\": [\n{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, \n{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, \n{\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, \n{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}], \n\"bicycle\": {\"color\": \"red\", \"price\": 19.95}, \"tools\": null}}`)\n\troot, err := ajson.Unmarshal(json)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tresult, err := ajson.Eval(root, \"avg($..price)\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(\"AVG price:\", result.MustNumeric())\n}\n```\n\n## Marshal\n\n[Playground](https://play.golang.org/p/i4gXXcA2VLU)\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/spyzhov/ajson\"\n)\n\nfunc main() {\n\tjson := []byte(`{\"store\": {\"book\": [\n{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, \n{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, \n{\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, \n{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}], \n\"bicycle\": {\"color\": \"red\", \"price\": 19.95}, \"tools\": null}}`)\n\troot := ajson.Must(ajson.Unmarshal(json))\n\tresult := ajson.Must(ajson.Eval(root, \"avg($..price)\"))\n\terr := root.AppendObject(\"price(avg)\", result)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tmarshalled, err := ajson.Marshal(root)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"%s\", marshalled)\n}\n```\n\n# Benchmarks\n\nCurrent package is comparable with `encoding/json` package. \n\nTest data:\n```json\n{ \"store\": {\n    \"book\": [ \n      { \"category\": \"reference\",\n        \"author\": \"Nigel Rees\",\n        \"title\": \"Sayings of the Century\",\n        \"price\": 8.95\n      },\n      { \"category\": \"fiction\",\n        \"author\": \"Evelyn Waugh\",\n        \"title\": \"Sword of Honour\",\n        \"price\": 12.99\n      },\n      { \"category\": \"fiction\",\n        \"author\": \"Herman Melville\",\n        \"title\": \"Moby Dick\",\n        \"isbn\": \"0-553-21311-3\",\n        \"price\": 8.99\n      },\n      { \"category\": \"fiction\",\n        \"author\": \"J. R. R. Tolkien\",\n        \"title\": \"The Lord of the Rings\",\n        \"isbn\": \"0-395-19395-8\",\n        \"price\": 22.99\n      }\n    ],\n    \"bicycle\": {\n      \"color\": \"red\",\n      \"price\": 19.95\n    }\n  }\n}\n```\nJSONPath: `$.store..price`\n\n```\n$ go test -bench=. -cpu=1 -benchmem\ngoos: linux\ngoarch: amd64\npkg: github.com/spyzhov/ajson\nBenchmarkUnmarshal_AJSON          121656             10060 ns/op            5712 B/op        118 allocs/op\nBenchmarkUnmarshal_JSON           102674             11381 ns/op             960 B/op         32 allocs/op\nBenchmarkJSONPath_all_prices       63314             16385 ns/op            7496 B/op        178 allocs/op\n```\n\n# License\n\nMIT licensed. See the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspyzhov%2Fajson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspyzhov%2Fajson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspyzhov%2Fajson/lists"}