{"id":15028898,"url":"https://github.com/jeffail/gabs","last_synced_at":"2025-05-12T15:28:59.019Z","repository":{"id":16530494,"uuid":"19283751","full_name":"Jeffail/gabs","owner":"Jeffail","description":"For parsing, creating and editing unknown or dynamic JSON in Go","archived":false,"fork":false,"pushed_at":"2024-06-06T20:46:33.000Z","size":414,"stargazers_count":3508,"open_issues_count":36,"forks_count":203,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-04-23T17:16:01.944Z","etag":null,"topics":["go","golang","json","parsing"],"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/Jeffail.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":{"github":"Jeffail"}},"created_at":"2014-04-29T16:38:26.000Z","updated_at":"2025-04-11T09:59:08.000Z","dependencies_parsed_at":"2023-01-16T20:02:17.540Z","dependency_job_id":"ccb838ff-24fd-47c6-81f9-d2bb5d072089","html_url":"https://github.com/Jeffail/gabs","commit_stats":{"total_commits":90,"total_committers":22,"mean_commits":4.090909090909091,"dds":0.7666666666666666,"last_synced_commit":"81fbfc23086ba576cb6ba8355a581e7c908f7553"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Fgabs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Fgabs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Fgabs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jeffail%2Fgabs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jeffail","download_url":"https://codeload.github.com/Jeffail/gabs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253765391,"owners_count":21960724,"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","json","parsing"],"created_at":"2024-09-24T20:09:18.954Z","updated_at":"2025-05-12T15:28:58.979Z","avatar_url":"https://github.com/Jeffail.png","language":"Go","readme":"![Gabs](gabs_logo.png \"Gabs\")\n\n[![pkg.go for Jeffail/gabs][godoc-badge]][godoc-url]\n\nGabs is a small utility for dealing with dynamic or unknown JSON structures in Go. It's pretty much just a helpful wrapper for navigating hierarchies of `map[string]interface{}` objects provided by the `encoding/json` package. It does nothing spectacular apart from being fabulous.\n\nIf you're migrating from version 1 check out [`migration.md`][migration-doc] for guidance.\n\n## Use\n\n### Import\n\nUsing modules:\n\n```go\nimport (\n\t\"github.com/Jeffail/gabs/v2\"\n)\n```\n\nWithout modules:\n\n```go\nimport (\n\t\"github.com/Jeffail/gabs\"\n)\n```\n\n### Parsing and searching JSON\n\n```go\njsonParsed, err := gabs.ParseJSON([]byte(`{\n\t\"outer\":{\n\t\t\"inner\":{\n\t\t\t\"value1\":10,\n\t\t\t\"value2\":22\n\t\t},\n\t\t\"alsoInner\":{\n\t\t\t\"value1\":20,\n\t\t\t\"array1\":[\n\t\t\t\t30, 40\n\t\t\t]\n\t\t}\n\t}\n}`))\nif err != nil {\n\tpanic(err)\n}\n\nvar value float64\nvar ok bool\n\nvalue, ok = jsonParsed.Path(\"outer.inner.value1\").Data().(float64)\n// value == 10.0, ok == true\n\nvalue, ok = jsonParsed.Search(\"outer\", \"inner\", \"value1\").Data().(float64)\n// value == 10.0, ok == true\n\nvalue, ok = jsonParsed.Search(\"outer\", \"alsoInner\", \"array1\", \"1\").Data().(float64)\n// value == 40.0, ok == true\n\ngObj, err := jsonParsed.JSONPointer(\"/outer/alsoInner/array1/1\")\nif err != nil {\n\tpanic(err)\n}\nvalue, ok = gObj.Data().(float64)\n// value == 40.0, ok == true\n\nvalue, ok = jsonParsed.Path(\"does.not.exist\").Data().(float64)\n// value == 0.0, ok == false\n\nexists := jsonParsed.Exists(\"outer\", \"inner\", \"value1\")\n// exists == true\n\nexists = jsonParsed.ExistsP(\"does.not.exist\")\n// exists == false\n```\n\n### Iterating objects\n\n```go\njsonParsed, err := gabs.ParseJSON([]byte(`{\"object\":{\"first\":1,\"second\":2,\"third\":3}}`))\nif err != nil {\n\tpanic(err)\n}\n\n// S is shorthand for Search\nfor key, child := range jsonParsed.S(\"object\").ChildrenMap() {\n\tfmt.Printf(\"key: %v, value: %v\\n\", key, child.Data().(float64))\n}\n```\n\n### Iterating arrays\n\n```go\njsonParsed, err := gabs.ParseJSON([]byte(`{\"array\":[\"first\",\"second\",\"third\"]}`))\nif err != nil {\n\tpanic(err)\n}\n\nfor _, child := range jsonParsed.S(\"array\").Children() {\n\tfmt.Println(child.Data().(string))\n}\n```\n\nWill print:\n\n```\nfirst\nsecond\nthird\n```\n\nChildren() will return all children of an array in order. This also works on objects, however, the children will be returned in a random order.\n\n### Searching through arrays\n\nIf your structure contains arrays you must target an index in your search.\n\n```go\njsonParsed, err := gabs.ParseJSON([]byte(`{\"array\":[{\"value\":1},{\"value\":2},{\"value\":3}]}`))\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(jsonParsed.Path(\"array.1.value\").String())\n```\n\nWill print `2`.\n\n### Generating JSON\n\n```go\njsonObj := gabs.New()\n// or gabs.Wrap(jsonObject) to work on an existing map[string]interface{}\n\njsonObj.Set(10, \"outer\", \"inner\", \"value\")\njsonObj.SetP(20, \"outer.inner.value2\")\njsonObj.Set(30, \"outer\", \"inner2\", \"value3\")\n\nfmt.Println(jsonObj.String())\n```\n\nWill print:\n\n```\n{\"outer\":{\"inner\":{\"value\":10,\"value2\":20},\"inner2\":{\"value3\":30}}}\n```\n\nTo pretty-print:\n\n```go\nfmt.Println(jsonObj.StringIndent(\"\", \"  \"))\n```\n\nWill print:\n\n```\n{\n  \"outer\": {\n    \"inner\": {\n      \"value\": 10,\n      \"value2\": 20\n    },\n    \"inner2\": {\n      \"value3\": 30\n    }\n  }\n}\n```\n\n### Generating Arrays\n\n```go\njsonObj := gabs.New()\n\njsonObj.Array(\"foo\", \"array\")\n// Or .ArrayP(\"foo.array\")\n\njsonObj.ArrayAppend(10, \"foo\", \"array\")\njsonObj.ArrayAppend(20, \"foo\", \"array\")\njsonObj.ArrayAppend(30, \"foo\", \"array\")\n\nfmt.Println(jsonObj.String())\n```\n\nWill print:\n\n```\n{\"foo\":{\"array\":[10,20,30]}}\n```\n\nWorking with arrays by index:\n\n```go\njsonObj := gabs.New()\n\n// Create an array with the length of 3\njsonObj.ArrayOfSize(3, \"foo\")\n\njsonObj.S(\"foo\").SetIndex(\"test1\", 0)\njsonObj.S(\"foo\").SetIndex(\"test2\", 1)\n\n// Create an embedded array with the length of 3\njsonObj.S(\"foo\").ArrayOfSizeI(3, 2)\n\njsonObj.S(\"foo\").Index(2).SetIndex(1, 0)\njsonObj.S(\"foo\").Index(2).SetIndex(2, 1)\njsonObj.S(\"foo\").Index(2).SetIndex(3, 2)\n\nfmt.Println(jsonObj.String())\n```\n\nWill print:\n\n```\n{\"foo\":[\"test1\",\"test2\",[1,2,3]]}\n```\n\n### Converting back to JSON\n\nThis is the easiest part:\n\n```go\njsonParsedObj, _ := gabs.ParseJSON([]byte(`{\n\t\"outer\":{\n\t\t\"values\":{\n\t\t\t\"first\":10,\n\t\t\t\"second\":11\n\t\t}\n\t},\n\t\"outer2\":\"hello world\"\n}`))\n\njsonOutput := jsonParsedObj.String()\n// Becomes `{\"outer\":{\"values\":{\"first\":10,\"second\":11}},\"outer2\":\"hello world\"}`\n```\n\nAnd to serialize a specific segment is as simple as:\n\n```go\njsonParsedObj := gabs.ParseJSON([]byte(`{\n\t\"outer\":{\n\t\t\"values\":{\n\t\t\t\"first\":10,\n\t\t\t\"second\":11\n\t\t}\n\t},\n\t\"outer2\":\"hello world\"\n}`))\n\njsonOutput := jsonParsedObj.Search(\"outer\").String()\n// Becomes `{\"values\":{\"first\":10,\"second\":11}}`\n```\n\n### Merge two containers\n\nYou can merge a JSON structure into an existing one, where collisions will be converted into a JSON array.\n\n```go\njsonParsed1, _ := ParseJSON([]byte(`{\"outer\":{\"value1\":\"one\"}}`))\njsonParsed2, _ := ParseJSON([]byte(`{\"outer\":{\"inner\":{\"value3\":\"three\"}},\"outer2\":{\"value2\":\"two\"}}`))\n\njsonParsed1.Merge(jsonParsed2)\n// Becomes `{\"outer\":{\"inner\":{\"value3\":\"three\"},\"value1\":\"one\"},\"outer2\":{\"value2\":\"two\"}}`\n```\n\nArrays are merged:\n\n```go\njsonParsed1, _ := ParseJSON([]byte(`{\"array\":[\"one\"]}`))\njsonParsed2, _ := ParseJSON([]byte(`{\"array\":[\"two\"]}`))\n\njsonParsed1.Merge(jsonParsed2)\n// Becomes `{\"array\":[\"one\", \"two\"]}`\n```\n\n### Parsing Numbers\n\nGabs uses the `json` package under the bonnet, which by default will parse all number values into `float64`. If you need to parse `Int` values then you should use a [`json.Decoder`](https://golang.org/pkg/encoding/json/#Decoder):\n\n```go\nsample := []byte(`{\"test\":{\"int\":10,\"float\":6.66}}`)\ndec := json.NewDecoder(bytes.NewReader(sample))\ndec.UseNumber()\n\nval, err := gabs.ParseJSONDecoder(dec)\nif err != nil {\n    t.Errorf(\"Failed to parse: %v\", err)\n    return\n}\n\nintValue, err := val.Path(\"test.int\").Data().(json.Number).Int64()\n```\n\n[godoc-badge]: https://godoc.org/github.com/Jeffail/gabs?status.svg\n[godoc-url]: https://pkg.go.dev/github.com/Jeffail/gabs/v2\n[migration-doc]: ./migration.md\n","funding_links":["https://github.com/sponsors/Jeffail"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffail%2Fgabs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffail%2Fgabs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffail%2Fgabs/lists"}