1![Gabs](gabs_logo.png "Gabs") 2 3Gabs is a small utility for dealing with dynamic or unknown JSON structures in 4golang. It's pretty much just a helpful wrapper around the golang 5`json.Marshal/json.Unmarshal` behaviour and `map[string]interface{}` objects. 6It does nothing spectacular except for being fabulous. 7 8https://godoc.org/github.com/Jeffail/gabs 9 10## Install 11 12``` bash 13go get github.com/Jeffail/gabs 14``` 15 16## Use 17 18### Parsing and searching JSON 19 20``` go 21jsonParsed, err := gabs.ParseJSON([]byte(`{ 22 "outter":{ 23 "inner":{ 24 "value1":10, 25 "value2":22 26 }, 27 "alsoInner":{ 28 "value1":20, 29 "array1":[ 30 30, 40 31 ] 32 } 33 } 34}`)) 35 36var value float64 37var ok bool 38 39value, ok = jsonParsed.Path("outter.inner.value1").Data().(float64) 40// value == 10.0, ok == true 41 42value, ok = jsonParsed.Search("outter", "inner", "value1").Data().(float64) 43// value == 10.0, ok == true 44 45gObj, err := jsonParsed.JSONPointer("/outter/alsoInner/array1/1") 46if err != nil { 47 panic(err) 48} 49value, ok = gObj.Data().(float64) 50// value == 40.0, ok == true 51 52value, ok = jsonParsed.Path("does.not.exist").Data().(float64) 53// value == 0.0, ok == false 54 55exists := jsonParsed.Exists("outter", "inner", "value1") 56// exists == true 57 58exists := jsonParsed.ExistsP("does.not.exist") 59// exists == false 60``` 61 62### Iterating objects 63 64``` go 65jsonParsed, _ := gabs.ParseJSON([]byte(`{"object":{ "first": 1, "second": 2, "third": 3 }}`)) 66 67// S is shorthand for Search 68children, _ := jsonParsed.S("object").ChildrenMap() 69for key, child := range children { 70 fmt.Printf("key: %v, value: %v\n", key, child.Data().(string)) 71} 72``` 73 74### Iterating arrays 75 76``` go 77jsonParsed, err := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`)) 78if err != nil { 79 panic(err) 80} 81 82// S is shorthand for Search 83children, err := jsonParsed.S("array").Children() 84if err != nil { 85 panic(err) 86} 87 88for _, child := range children { 89 fmt.Println(child.Data().(string)) 90} 91``` 92 93Will print: 94 95``` 96first 97second 98third 99``` 100 101Children() will return all children of an array in order. This also works on 102objects, however, the children will be returned in a random order. 103 104### Searching through arrays 105 106If your JSON structure contains arrays you can still search the fields of the 107objects within the array, this returns a JSON array containing the results for 108each element. 109 110``` go 111jsonParsed, err := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`)) 112if err != nil { 113 panic(err) 114} 115fmt.Println(jsonParsed.Path("array.value").String()) 116``` 117 118Will print: 119 120``` 121[1,2,3] 122``` 123 124### Generating JSON 125 126``` go 127jsonObj := gabs.New() 128// or gabs.Consume(jsonObject) to work on an existing map[string]interface{} 129 130jsonObj.Set(10, "outter", "inner", "value") 131jsonObj.SetP(20, "outter.inner.value2") 132jsonObj.Set(30, "outter", "inner2", "value3") 133 134fmt.Println(jsonObj.String()) 135``` 136 137Will print: 138 139``` 140{"outter":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}} 141``` 142 143To pretty-print: 144 145``` go 146fmt.Println(jsonObj.StringIndent("", " ")) 147``` 148 149Will print: 150 151``` 152{ 153 "outter": { 154 "inner": { 155 "value": 10, 156 "value2": 20 157 }, 158 "inner2": { 159 "value3": 30 160 } 161 } 162} 163``` 164 165### Generating Arrays 166 167``` go 168jsonObj := gabs.New() 169 170jsonObj.Array("foo", "array") 171// Or .ArrayP("foo.array") 172 173jsonObj.ArrayAppend(10, "foo", "array") 174jsonObj.ArrayAppend(20, "foo", "array") 175jsonObj.ArrayAppend(30, "foo", "array") 176 177fmt.Println(jsonObj.String()) 178``` 179 180Will print: 181 182``` 183{"foo":{"array":[10,20,30]}} 184``` 185 186Working with arrays by index: 187 188``` go 189jsonObj := gabs.New() 190 191// Create an array with the length of 3 192jsonObj.ArrayOfSize(3, "foo") 193 194jsonObj.S("foo").SetIndex("test1", 0) 195jsonObj.S("foo").SetIndex("test2", 1) 196 197// Create an embedded array with the length of 3 198jsonObj.S("foo").ArrayOfSizeI(3, 2) 199 200jsonObj.S("foo").Index(2).SetIndex(1, 0) 201jsonObj.S("foo").Index(2).SetIndex(2, 1) 202jsonObj.S("foo").Index(2).SetIndex(3, 2) 203 204fmt.Println(jsonObj.String()) 205``` 206 207Will print: 208 209``` 210{"foo":["test1","test2",[1,2,3]]} 211``` 212 213### Converting back to JSON 214 215This is the easiest part: 216 217``` go 218jsonParsedObj, _ := gabs.ParseJSON([]byte(`{ 219 "outter":{ 220 "values":{ 221 "first":10, 222 "second":11 223 } 224 }, 225 "outter2":"hello world" 226}`)) 227 228jsonOutput := jsonParsedObj.String() 229// Becomes `{"outter":{"values":{"first":10,"second":11}},"outter2":"hello world"}` 230``` 231 232And to serialize a specific segment is as simple as: 233 234``` go 235jsonParsedObj := gabs.ParseJSON([]byte(`{ 236 "outter":{ 237 "values":{ 238 "first":10, 239 "second":11 240 } 241 }, 242 "outter2":"hello world" 243}`)) 244 245jsonOutput := jsonParsedObj.Search("outter").String() 246// Becomes `{"values":{"first":10,"second":11}}` 247``` 248 249### Merge two containers 250 251You can merge a JSON structure into an existing one, where collisions will be 252converted into a JSON array. 253 254``` go 255jsonParsed1, _ := ParseJSON([]byte(`{"outter": {"value1": "one"}}`)) 256jsonParsed2, _ := ParseJSON([]byte(`{"outter": {"inner": {"value3": "three"}}, "outter2": {"value2": "two"}}`)) 257 258jsonParsed1.Merge(jsonParsed2) 259// Becomes `{"outter":{"inner":{"value3":"three"},"value1":"one"},"outter2":{"value2":"two"}}` 260``` 261 262Arrays are merged: 263 264``` go 265jsonParsed1, _ := ParseJSON([]byte(`{"array": ["one"]}`)) 266jsonParsed2, _ := ParseJSON([]byte(`{"array": ["two"]}`)) 267 268jsonParsed1.Merge(jsonParsed2) 269// Becomes `{"array":["one", "two"]}` 270``` 271 272### Parsing Numbers 273 274Gabs uses the `json` package under the bonnet, which by default will parse all 275number values into `float64`. If you need to parse `Int` values then you should 276use a `json.Decoder` (https://golang.org/pkg/encoding/json/#Decoder): 277 278``` go 279sample := []byte(`{"test":{"int":10, "float":6.66}}`) 280dec := json.NewDecoder(bytes.NewReader(sample)) 281dec.UseNumber() 282 283val, err := gabs.ParseJSONDecoder(dec) 284if err != nil { 285 t.Errorf("Failed to parse: %v", err) 286 return 287} 288 289intValue, err := val.Path("test.int").Data().(json.Number).Int64() 290``` 291