README.md

  1<p align="center">
  2<img 
  3    src="logo.png" 
  4    width="240" height="78" border="0" alt="SJSON">
  5<br>
  6<a href="https://godoc.org/github.com/tidwall/sjson"><img src="https://img.shields.io/badge/api-reference-blue.svg?style=flat-square" alt="GoDoc"></a>
  7</p>
  8
  9<p align="center">set a json value quickly</p>
 10
 11SJSON is a Go package that provides a [very fast](#performance) and simple way to set a value in a json document.
 12For quickly retrieving json values check out [GJSON](https://github.com/tidwall/gjson).
 13
 14For a command line interface check out [JJ](https://github.com/tidwall/jj).
 15
 16Getting Started
 17===============
 18
 19Installing
 20----------
 21
 22To start using SJSON, install Go and run `go get`:
 23
 24```sh
 25$ go get -u github.com/tidwall/sjson
 26```
 27
 28This will retrieve the library.
 29
 30Set a value
 31-----------
 32Set sets the value for the specified path. 
 33A path is in dot syntax, such as "name.last" or "age". 
 34This function expects that the json is well-formed and validated. 
 35Invalid json will not panic, but it may return back unexpected results.
 36Invalid paths may return an error.
 37
 38```go
 39package main
 40
 41import "github.com/tidwall/sjson"
 42
 43const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
 44
 45func main() {
 46	value, _ := sjson.Set(json, "name.last", "Anderson")
 47	println(value)
 48}
 49```
 50
 51This will print:
 52
 53```json
 54{"name":{"first":"Janet","last":"Anderson"},"age":47}
 55```
 56
 57Path syntax
 58-----------
 59
 60A path is a series of keys separated by a dot.
 61The dot and colon characters can be escaped with ``\``.
 62
 63```json
 64{
 65  "name": {"first": "Tom", "last": "Anderson"},
 66  "age":37,
 67  "children": ["Sara","Alex","Jack"],
 68  "fav.movie": "Deer Hunter",
 69  "friends": [
 70	{"first": "James", "last": "Murphy"},
 71	{"first": "Roger", "last": "Craig"}
 72  ]
 73}
 74```
 75```
 76"name.last"          >> "Anderson"
 77"age"                >> 37
 78"children.1"         >> "Alex"
 79"friends.1.last"     >> "Craig"
 80```
 81
 82The `-1` key can be used to append a value to an existing array:
 83
 84```
 85"children.-1"  >> appends a new value to the end of the children array
 86```
 87
 88Normally number keys are used to modify arrays, but it's possible to force a numeric object key by using the colon character:
 89
 90```json
 91{
 92  "users":{
 93    "2313":{"name":"Sara"},
 94    "7839":{"name":"Andy"}
 95  }
 96}
 97```
 98
 99A colon path would look like:
100
101```
102"users.:2313.name"    >> "Sara"
103```
104
105Supported types
106---------------
107
108Pretty much any type is supported:
109
110```go
111sjson.Set(`{"key":true}`, "key", nil)
112sjson.Set(`{"key":true}`, "key", false)
113sjson.Set(`{"key":true}`, "key", 1)
114sjson.Set(`{"key":true}`, "key", 10.5)
115sjson.Set(`{"key":true}`, "key", "hello")
116sjson.Set(`{"key":true}`, "key", []string{"hello", "world"})
117sjson.Set(`{"key":true}`, "key", map[string]interface{}{"hello":"world"})
118```
119
120When a type is not recognized, SJSON will fallback to the `encoding/json` Marshaller.
121
122
123Examples
124--------
125
126Set a value from empty document:
127```go
128value, _ := sjson.Set("", "name", "Tom")
129println(value)
130
131// Output:
132// {"name":"Tom"}
133```
134
135Set a nested value from empty document:
136```go
137value, _ := sjson.Set("", "name.last", "Anderson")
138println(value)
139
140// Output:
141// {"name":{"last":"Anderson"}}
142```
143
144Set a new value:
145```go
146value, _ := sjson.Set(`{"name":{"last":"Anderson"}}`, "name.first", "Sara")
147println(value)
148
149// Output:
150// {"name":{"first":"Sara","last":"Anderson"}}
151```
152
153Update an existing value:
154```go
155value, _ := sjson.Set(`{"name":{"last":"Anderson"}}`, "name.last", "Smith")
156println(value)
157
158// Output:
159// {"name":{"last":"Smith"}}
160```
161
162Set a new array value:
163```go
164value, _ := sjson.Set(`{"friends":["Andy","Carol"]}`, "friends.2", "Sara")
165println(value)
166
167// Output:
168// {"friends":["Andy","Carol","Sara"]
169```
170
171Append an array value by using the `-1` key in a path:
172```go
173value, _ := sjson.Set(`{"friends":["Andy","Carol"]}`, "friends.-1", "Sara")
174println(value)
175
176// Output:
177// {"friends":["Andy","Carol","Sara"]
178```
179
180Append an array value that is past the end:
181```go
182value, _ := sjson.Set(`{"friends":["Andy","Carol"]}`, "friends.4", "Sara")
183println(value)
184
185// Output:
186// {"friends":["Andy","Carol",null,null,"Sara"]
187```
188
189Delete a value:
190```go
191value, _ := sjson.Delete(`{"name":{"first":"Sara","last":"Anderson"}}`, "name.first")
192println(value)
193
194// Output:
195// {"name":{"last":"Anderson"}}
196```
197
198Delete an array value:
199```go
200value, _ := sjson.Delete(`{"friends":["Andy","Carol"]}`, "friends.1")
201println(value)
202
203// Output:
204// {"friends":["Andy"]}
205```
206
207Delete the last array value:
208```go
209value, _ := sjson.Delete(`{"friends":["Andy","Carol"]}`, "friends.-1")
210println(value)
211
212// Output:
213// {"friends":["Andy"]}
214```
215
216## Performance
217
218Benchmarks of SJSON alongside [encoding/json](https://golang.org/pkg/encoding/json/), 
219[ffjson](https://github.com/pquerna/ffjson), 
220[EasyJSON](https://github.com/mailru/easyjson),
221and [Gabs](https://github.com/Jeffail/gabs)
222
223```
224Benchmark_SJSON-8                  	 3000000	       805 ns/op	    1077 B/op	       3 allocs/op
225Benchmark_SJSON_ReplaceInPlace-8   	 3000000	       449 ns/op	       0 B/op	       0 allocs/op
226Benchmark_JSON_Map-8               	  300000	     21236 ns/op	    6392 B/op	     150 allocs/op
227Benchmark_JSON_Struct-8            	  300000	     14691 ns/op	    1789 B/op	      24 allocs/op
228Benchmark_Gabs-8                   	  300000	     21311 ns/op	    6752 B/op	     150 allocs/op
229Benchmark_FFJSON-8                 	  300000	     17673 ns/op	    3589 B/op	      47 allocs/op
230Benchmark_EasyJSON-8               	 1500000	      3119 ns/op	    1061 B/op	      13 allocs/op
231```
232
233JSON document used:
234
235```json
236{
237  "widget": {
238    "debug": "on",
239    "window": {
240      "title": "Sample Konfabulator Widget",
241      "name": "main_window",
242      "width": 500,
243      "height": 500
244    },
245    "image": { 
246      "src": "Images/Sun.png",
247      "hOffset": 250,
248      "vOffset": 250,
249      "alignment": "center"
250    },
251    "text": {
252      "data": "Click Here",
253      "size": 36,
254      "style": "bold",
255      "vOffset": 100,
256      "alignment": "center",
257      "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
258    }
259  }
260}    
261```
262
263Each operation was rotated though one of the following search paths:
264
265```
266widget.window.name
267widget.image.hOffset
268widget.text.onMouseUp
269```
270
271*These benchmarks were run on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.7 and can be be found [here](https://github.com/tidwall/sjson-benchmarks)*.
272
273## Contact
274Josh Baker [@tidwall](http://twitter.com/tidwall)
275
276## License
277
278SJSON source code is available under the MIT [License](/LICENSE).