2 `jsonpatch` is a library which provides functionallity for both applying
3 [RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as
4 well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
6 [![GoDoc](https://godoc.org/github.com/evanphx/json-patch?status.svg)](http://godoc.org/github.com/evanphx/json-patch)
7 [![Build Status](https://travis-ci.org/evanphx/json-patch.svg?branch=master)](https://travis-ci.org/evanphx/json-patch)
8 [![Report Card](https://goreportcard.com/badge/github.com/evanphx/json-patch)](https://goreportcard.com/report/github.com/evanphx/json-patch)
12 **Latest and greatest**:
14 go get -u github.com/evanphx/json-patch
18 * Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
20 (previous versions below `v3` are unavailable)
23 * [Create and apply a merge patch](#create-and-apply-a-merge-patch)
24 * [Create and apply a JSON Patch](#create-and-apply-a-json-patch)
25 * [Comparing JSON documents](#comparing-json-documents)
26 * [Combine merge patches](#combine-merge-patches)
31 There is a single global configuration variable `jsonpatch.SupportNegativeIndices'. This
32 defaults to `true` and enables the non-standard practice of allowing negative indices
33 to mean indices starting at the end of an array. This functionality can be disabled
34 by setting `jsonpatch.SupportNegativeIndices = false`.
36 ## Create and apply a merge patch
37 Given both an original JSON document and a modified JSON document, you can create
38 a [Merge Patch](https://tools.ietf.org/html/rfc7396) document.
40 It can describe the changes needed to convert from the original to the
41 modified JSON document.
43 Once you have a merge patch, you can apply it to other JSON documents using the
44 `jsonpatch.MergePatch(document, patch)` function.
52 jsonpatch "github.com/evanphx/json-patch"
56 // Let's create a merge patch from these two documents...
57 original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
58 target := []byte(`{"name": "Jane", "age": 24}`)
60 patch, err := jsonpatch.CreateMergePatch(original, target)
65 // Now lets apply the patch against a different JSON document...
67 alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`)
68 modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)
70 fmt.Printf("patch document: %s\n", patch)
71 fmt.Printf("updated alternative doc: %s\n", modifiedAlternative)
75 When ran, you get the following output:
79 patch document: {"height":null,"name":"Jane"}
80 updated tina doc: {"age":28,"name":"Jane"}
83 ## Create and apply a JSON Patch
84 You can create patch objects using `DecodePatch([]byte)`, which can then
85 be applied against JSON documents.
87 The following is an example of creating a patch from two operations, and
88 applying it against a JSON document.
96 jsonpatch "github.com/evanphx/json-patch"
100 original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
101 patchJSON := []byte(`[
102 {"op": "replace", "path": "/name", "value": "Jane"},
103 {"op": "remove", "path": "/height"}
106 patch, err := jsonpatch.DecodePatch(patchJSON)
111 modified, err := patch.Apply(original)
116 fmt.Printf("Original document: %s\n", original)
117 fmt.Printf("Modified document: %s\n", modified)
121 When ran, you get the following output:
125 Original document: {"name": "John", "age": 24, "height": 3.21}
126 Modified document: {"age":24,"name":"Jane"}
129 ## Comparing JSON documents
130 Due to potential whitespace and ordering differences, one cannot simply compare
131 JSON strings or byte-arrays directly.
133 As such, you can instead use `jsonpatch.Equal(document1, document2)` to
134 determine if two JSON documents are _structurally_ equal. This ignores
135 whitespace differences, and key-value ordering.
143 jsonpatch "github.com/evanphx/json-patch"
147 original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
155 different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`)
157 if jsonpatch.Equal(original, similar) {
158 fmt.Println(`"original" is structurally equal to "similar"`)
161 if !jsonpatch.Equal(original, different) {
162 fmt.Println(`"original" is _not_ structurally equal to "similar"`)
167 When ran, you get the following output:
170 "original" is structurally equal to "similar"
171 "original" is _not_ structurally equal to "similar"
174 ## Combine merge patches
175 Given two JSON merge patch documents, it is possible to combine them into a
176 single merge patch which can describe both set of changes.
178 The resulting merge patch can be used such that applying it results in a
179 document structurally similar as merging each merge patch to the document
188 jsonpatch "github.com/evanphx/json-patch"
192 original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
194 nameAndHeight := []byte(`{"height":null,"name":"Jane"}`)
195 ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`)
197 // Let's combine these merge patch documents...
198 combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)
203 // Apply each patch individual against the original document
204 withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)
209 withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)
214 // Apply the combined patch against the original document
216 withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)
221 // Do both result in the same thing? They should!
222 if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {
223 fmt.Println("Both JSON documents are structurally the same!")
226 fmt.Printf("combined merge patch: %s", combinedPatch)
230 When ran, you get the following output:
233 Both JSON documents are structurally the same!
234 combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"}
237 # CLI for comparing JSON documents
238 You can install the commandline program `json-patch`.
240 This program can take multiple JSON patch documents as arguments,
241 and fed a JSON document from `stdin`. It will apply the patch(es) against
242 the document and output the modified doc.
247 {"op": "replace", "path": "/name", "value": "Jane"},
248 {"op": "remove", "path": "/height"}
255 {"op": "add", "path": "/address", "value": "123 Main St"},
256 {"op": "replace", "path": "/age", "value": "21"}
272 $ go install github.com/evanphx/json-patch/cmd/json-patch
273 $ cat document.json | json-patch -p patch.1.json -p patch.2.json
274 {"address":"123 Main St","age":"21","name":"Jane"}
278 Contributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues)
279 or [create a PR](https://github.com/evanphx/json-patch/compare).
282 Before creating a pull request, we'd ask that you make sure tests are passing
283 and that you have added new tests when applicable.
285 Contributors can run tests using:
291 Builds for pull requests are tested automatically
292 using [TravisCI](https://travis-ci.org/evanphx/json-patch).