{"id":22450641,"url":"https://github.com/xieyuschen/astjson","last_synced_at":"2025-03-27T12:18:49.956Z","repository":{"id":201170145,"uuid":"702963923","full_name":"xieyuschen/astjson","owner":"xieyuschen","description":"Go AST Json Library Exposes AST to Manipulate in an FP way","archived":false,"fork":false,"pushed_at":"2023-11-14T06:03:21.000Z","size":47,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-01T16:48:25.110Z","etag":null,"topics":["ast","go","parser"],"latest_commit_sha":null,"homepage":"","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/xieyuschen.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-10T10:43:06.000Z","updated_at":"2024-08-14T02:40:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"78ab9ffd-dd7f-48eb-9650-27899f9609af","html_url":"https://github.com/xieyuschen/astjson","commit_stats":null,"previous_names":["xieyuschen/astjson"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xieyuschen%2Fastjson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xieyuschen%2Fastjson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xieyuschen%2Fastjson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xieyuschen%2Fastjson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xieyuschen","download_url":"https://codeload.github.com/xieyuschen/astjson/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245841761,"owners_count":20681195,"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":["ast","go","parser"],"created_at":"2024-12-06T05:16:57.468Z","updated_at":"2025-03-27T12:18:49.936Z","avatar_url":"https://github.com/xieyuschen.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# astjson\n[![codecov](https://codecov.io/gh/xieyuschen/astjson/graph/badge.svg?token=FFXVZQYUWF)](https://codecov.io/gh/xieyuschen/astjson)\n\n## Requirement\nAstjson requires at least `go1.18` as it uses some features from reflect library.\n\n```shell\ngo get github.com/xieyuschen/astjson\n```\n\n## Example\n\n```go\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/xieyuschen/astjson\"\n)\n\nconst (\n\tjsonStr = `\n{\n  \"num\": 999,\n  \"str\": \"helloworld\",\n  \"enabled\": true ,\n  \"sub1\": {\n    \"sub2\": {\n      \"key\": 999\n    }\n  },\n  \"name\": \"astjson\"\n}`\n)\n\ntype (\n\tSub1 struct {\n\t\tSub2 Sub2 `json:\"sub2\"`\n\t}\n\tSub2 struct {\n\t\tKey int `json:\"key\"`\n\t}\n\tdemo struct {\n\t\tNum     int    `json:\"num\"`\n\t\tStr     string `json:\"str\"`\n\t\tEnabled bool   `json:\"enabled\"`\n\t\tSub     Sub1   `json:\"sub1\"`\n\t}\n)\n\nfunc main() {\n\n\tastValue := astjson.NewParser([]byte(jsonStr)).Parse()\n\n\tval, err := astjson.NewWalker(astValue).\n\t\t// field \"str\" is required\n\t\tField(\"str\").\n\t\t// field \"num\" is optional, but if it exists the validator will be triggered\n\t\tOptional(\"num\", equal999).\n\t\tField(\"enabled\").Validate(isTrue).\n\t\tPath(\"sub1\").Path(\"sub2\").Validate(equal999).EndPath().\n\t\tValidateKey(\"name\", hasAstjsonName).\n\t\tWalk()\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tvar d demo\n\t_ = astjson.NewDecoder().Unmarshal(val, \u0026d)\n\tfmt.Println(d)\n}\n\nfunc equal999(value *astjson.Value) error {\n\tactual := value.AstValue.(astjson.NumberAst).GetInt64()\n\tif actual == 999 {\n\t\treturn nil\n\t}\n\treturn errors.New(\"num should be 999\")\n}\n\nfunc isTrue(value *astjson.Value) error {\n\tif bool(value.AstValue.(astjson.BoolAst)) {\n\t\treturn nil\n\t}\n\treturn errors.New(\"bool should be true\")\n}\nfunc hasAstjsonName(value *astjson.Value) error {\n\tif value.AstValue.(astjson.StringAst) == \"astjson\" {\n\t\treturn nil\n\t}\n\treturn errors.New(\"name should be astjson\")\n}\n```\n\nSee more [examples here](astjson_example_test.go).\n\n## Motivation\nHaskell json library [aeson](https://github.com/haskell/aeson) parsed AST first in its early version as a default way.\nHowever, it skips to convert AST first to speed up parsing as a new default way.\n\nParsing AST first is slower than directly parsing json, however, it provides more flexibilities.\nHence, inspired by aeson, I wrote a ast json to help parsing json to AST.\n\n- [json tokens](https://www.json.org/json-en.html)\n- [aeson](https://hackage.haskell.org/package/aeson-2.2.1.0/docs/Data-Aeson.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxieyuschen%2Fastjson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxieyuschen%2Fastjson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxieyuschen%2Fastjson/lists"}