{"id":15521892,"url":"https://github.com/crossoverjie/xjson","last_synced_at":"2025-09-07T21:35:19.800Z","repository":{"id":40239332,"uuid":"507379743","full_name":"crossoverJie/xjson","owner":"crossoverJie","description":"🧮JSON parser for Go, Support Query and Arithmetic operations.","archived":false,"fork":false,"pushed_at":"2022-09-09T16:51:24.000Z","size":156,"stargazers_count":48,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-23T03:51:54.373Z","etag":null,"topics":["arithmetic","go","json","parser"],"latest_commit_sha":null,"homepage":"https://crossoverjie.top/categories/xjson/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crossoverJie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-25T17:49:35.000Z","updated_at":"2024-08-27T21:23:16.000Z","dependencies_parsed_at":"2022-06-27T01:34:59.792Z","dependency_job_id":null,"html_url":"https://github.com/crossoverJie/xjson","commit_stats":null,"previous_names":["crossoverjie/gjson"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/crossoverJie/xjson","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crossoverJie%2Fxjson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crossoverJie%2Fxjson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crossoverJie%2Fxjson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crossoverJie%2Fxjson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crossoverJie","download_url":"https://codeload.github.com/crossoverJie/xjson/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crossoverJie%2Fxjson/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274100873,"owners_count":25222444,"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","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"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":["arithmetic","go","json","parser"],"created_at":"2024-10-02T10:38:27.235Z","updated_at":"2025-09-07T21:35:19.770Z","avatar_url":"https://github.com/crossoverJie.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n\u003cimg \n    src=\"xjson.png\" \n    width=\"300\" height=\"270\" border=\"0\" alt=\"xjson\"\u003e\n\u003cbr\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://goreportcard.com/report/github.com/crossoverJie/xjson\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/crossoverJie/xjson\"\u003e\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/crossoverJie/xjson\"\u003e\u003cimg src=\"https://codecov.io/gh/crossoverJie/xjson/branch/main/graph/badge.svg?token=51WIOVFN95\"\u003e\u003c/a\u003e\n\u003cbr\u003e\nQuery and Arithmetic\n\u003c/p\u003e\n\n\n`xjson` is a `JSON` parsing library, you can query `JSON` like `OOP`. \n\n```go\nstr := `{\"people\":{\"name\":{\"first\":\"bob\"}}}`\nfirst := xjson.Get(str, \"people.name.first\")\nassert.Equal(t, first.String(), \"bob\")\nget := xjson.Get(str, \"people\")\nassert.Equal(t, get.String(),`{\"name\":{\"first\":\"bob\"}}`)\n```\n\nEven perform arithmetic operations with `JSON`.\n\n```go\nstr := `{\"people\":[{\"bob\":{\"age\":10}},{\"alice\":{\"age\":10}}]}`\nage := xjson.GetWithArithmetic(str, \"people[0].bob.age + people[1].alice.age\")\nassert.Equal(t, age.Int(), 20)\n\ngrammar := `\nif ((people[0].bob.age + people[1].alice.age)==20){\n\treturn true\n}else{\n\treturn 20\n}\n`\nret := xjson.GetWithArithmetic(str, grammar)\nassert.Equal(t, ret.Bool(), true)\n```\n\nInstalling:\n\n```shell\ngo get github.com/crossoverJie/xjson\n```\n\n# Query Syntax\n\n- Use dot `.` to indicate object nesting relationships.\n- Use `[index]` indicate an array.\n\n```go\nstr := `\n{\n\"name\": \"bob\",\n\"age\": 20,\n\"skill\": {\n    \"lang\": [\n        {\n            \"go\": {\n                \"feature\": [\n                    \"goroutine\",\n                    \"channel\",\n                    \"simple\",\n                    true\n                ]\n            }\n        }\n    ]\n}\n}`\n\nname := xjson.Get(str, \"name\")\nassert.Equal(t, name.String(), \"bob\")\n\nage := xjson.Get(str, \"age\")\nassert.Equal(t, age.Int(), 20)\n\nassert.Equal(t, xjson.Get(str,\"skill.lang[0].go.feature[0]\").String(), \"goroutine\")\nassert.Equal(t, xjson.Get(str,\"skill.lang[0].go.feature[1]\").String(), \"channel\")\nassert.Equal(t, xjson.Get(str,\"skill.lang[0].go.feature[2]\").String(), \"simple\")\nassert.Equal(t, xjson.Get(str,\"skill.lang[0].go.feature[3]\").Bool(), true)\n\n// escape\nstr := `{\"1a.\":\"b\"}`\nget := Get(str, \"1a\\\\.\")\nassert.Equal(t, get.String(), \"b\")\n```\n\nThe tow syntax work together to obtain complex nested `JSON` data.\n\n# Arithmetic Syntax\n\n`xjson` supports `+ - * / % ()` arithmetic operations.\n\n```go\nstr := `{\"name\":\"bob\", \"age\":10,\"magic\":10.1, \"score\":{\"math\":[1,2]}}`\nresult := xjson.GetWithArithmetic(str, \"(age+age)*age+magic\")\nassert.Equal(t, result.Float(), 210.1)\nresult = xjson.GetWithArithmetic(str, \"(age+age)*age\")\nassert.Equal(t, result.Int(), 200)\n\nresult = xjson.GetWithArithmetic(str, \"(age+age) * age + score.math[0]\")\nassert.Equal(t, result.Int(), 201)\n\nresult = xjson.GetWithArithmetic(str, \"(age+age) * age - score.math[0]\")\nassert.Equal(t, result.Int(), 199)\n```\n\n**Attention**:\n\n- Only **int/float** are supported.\n- When other types(`string/bool/null..`) exist, the empty `Result` will be returned.\n- When `int` and `float` are caculated, **float** will be returned.\n\n# Result\n\nBoth `Get()/GetWithArithmetic` will return `Result` type.\n\n\nIt provides the following methods to help us obtain data more easily.\n\n```go\nfunc (r Result) String() string\nfunc (r Result) Bool() bool\nfunc (r Result) Int() int\nfunc (r Result) Float() float64\nfunc (r Result) Map() map[string]interface{}\nfunc (r Result) Array() []interface{}\nfunc (r Result) Exists() bool\n```\n\n\u003e You can tell what they mean from their names.\n\n# Other APIs\n\n## Decode\n\nIt can convert `JSON` strings to `interface{}`.\n\n```go\nfunc TestJson(t *testing.T) {\n\tstr := `{\n   \"glossary\": {\n       \"title\": \"example glossary\",\n\t\t\"age\":1,\n\t\t\"long\":99.99,\n\t\t\"GlossDiv\": {\n           \"title\": \"S\",\n\t\t\t\"GlossList\": {\n               \"GlossEntry\": {\n                   \"ID\": \"SGML\",\n\t\t\t\t\t\"SortAs\": \"SGML\",\n\t\t\t\t\t\"GlossTerm\": \"Standard Generalized Markup Language\",\n\t\t\t\t\t\"Acronym\": \"SGML\",\n\t\t\t\t\t\"Abbrev\": \"ISO 8879:1986\",\n\t\t\t\t\t\"GlossDef\": {\n                       \"para\": \"A meta-markup language, used to create markup languages such as DocBook.\",\n\t\t\t\t\t\t\"GlossSeeAlso\": [\"GML\", \"XML\", true, null]\n                   },\n\t\t\t\t\t\"GlossSee\": \"markup\"\n               }\n           }\n       }\n   }\n}`\n\tdecode, err := xjson.Decode(str)\n\tassert.Nil(t, err)\n\tfmt.Println(decode)\n\tv := decode.(map[string]interface{})\n\tglossary := v[\"glossary\"].(map[string]interface{})\n\tassert.Equal(t, glossary[\"title\"], \"example glossary\")\n\tassert.Equal(t, glossary[\"age\"], 1)\n\tassert.Equal(t, glossary[\"long\"], 99.99)\n\tglossDiv := glossary[\"GlossDiv\"].(map[string]interface{})\n\tassert.Equal(t, glossDiv[\"title\"], \"S\")\n\tglossList := glossDiv[\"GlossList\"].(map[string]interface{})\n\tglossEntry := glossList[\"GlossEntry\"].(map[string]interface{})\n\tassert.Equal(t, glossEntry[\"ID\"], \"SGML\")\n\tassert.Equal(t, glossEntry[\"SortAs\"], \"SGML\")\n\tassert.Equal(t, glossEntry[\"GlossTerm\"], \"Standard Generalized Markup Language\")\n\tassert.Equal(t, glossEntry[\"Acronym\"], \"SGML\")\n\tassert.Equal(t, glossEntry[\"Abbrev\"], \"ISO 8879:1986\")\n\tglossDef := glossEntry[\"GlossDef\"].(map[string]interface{})\n\tassert.Equal(t, glossDef[\"para\"], \"A meta-markup language, used to create markup languages such as DocBook.\")\n\tglossSeeAlso := glossDef[\"GlossSeeAlso\"].(*[]interface{})\n\tassert.Equal(t, (*glossSeeAlso)[0], \"GML\")\n\tassert.Equal(t, (*glossSeeAlso)[1], \"XML\")\n\tassert.Equal(t, (*glossSeeAlso)[2], true)\n\tassert.Equal(t, (*glossSeeAlso)[3], \"\")\n\tassert.Equal(t, glossEntry[\"GlossSee\"], \"markup\")\n}\n```\n\n# Features\n- [x] Support syntax: `xjson.Get(\"glossary.title\")`\n- [x] Support arithmetic operators: `xjson.Get(\"glossary.age+long\")`\n- [x] Support escape.\n- [ ] Resolve to struct\n\n# Acknowledgements\n\n[gjson](https://github.com/tidwall/gjson)\n\n[gscript](https://github.com/crossoverjie/gscript)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrossoverjie%2Fxjson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrossoverjie%2Fxjson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrossoverjie%2Fxjson/lists"}