Package: wnpp Severity: wishlist Owner: Rafael Passos <[email protected]>
* Package name : golang-gopkg-evanphx-json-patch.v4 Version : 4.13.0-1 Upstream Author : Evan Phoenix * URL : https://github.com/evanphx/json-patch * License : BSD-3-clause Programming Lang: Go Description : A Go library to apply RFC6902 patches and create and apply RFC7386 patches JSON-Patch . jsonpatch is a library which provides functionality for both applying RFC6902 JSON patches (http://tools.ietf.org/html/rfc6902) against documents, as well as for calculating & applying RFC7396 JSON merge patches (https://tools.ietf.org/html/rfc7396). . [Image: GoDoc] (https://godoc.org/github.com/evanphx/json- patch?status.svg) (http://godoc.org/github.com/evanphx/json-patch) [Image: Build Status] (https://github.com/evanphx/json- patch/actions/workflows/go.yml/badge.svg) (https://github.com/evanphx/json-patch/actions/workflows/go.yml) [Image: Report Card] (https://goreportcard.com/badge/github.com/evanphx/json- patch) (https://goreportcard.com/report/github.com/evanphx/json-patch) . Get It! . **Latest and greatest**: . go get -u github.com/evanphx/json-patch/v5 . If you need version 4, use go get -u gopkg.in/evanphx/json-patch.v4 . (previous versions below v3 are unavailable) . Use It! . * Create and apply a merge patch * Create and apply a JSON Patch * Comparing JSON documents * Combine merge patches . Configuration . * There is a global configuration variable jsonpatch. SupportNegativeIndices. This defaults to true and enables the non-standard practice of allowing negative indices to mean indices starting at the end of an array. This functionality can be disabled by setting jsonpatch. SupportNegativeIndices = false. * There is a global configuration variable jsonpatch. AccumulatedCopySizeLimit, which limits the total size increase in bytes caused by "copy" operations in a patch. It defaults to 0, which means there is no limit. . These global variables control the behavior of jsonpatch.Apply. . An alternative to jsonpatch.Apply is jsonpatch.ApplyWithOptions whose behavior is controlled by an options parameter of type *jsonpatch.ApplyOptions. . Structure jsonpatch.ApplyOptions includes the configuration options above and adds two new options: AllowMissingPathOnRemove and EnsurePathExistsOnAdd. . When AllowMissingPathOnRemove is set to true, jsonpatch.ApplyWithOptions will ignore remove operations whose path points to a non-existent location in the JSON document. AllowMissingPathOnRemove defaults to false which will lead to jsonpatch.ApplyWithOptions returning an error when hitting a missing path on remove. . When EnsurePathExistsOnAdd is set to true, jsonpatch.ApplyWithOptions will make sure that add operations produce all the path elements that are missing from the target object. . Use jsonpatch.NewApplyOptions to create an instance of jsonpatch.ApplyOptions whose values are populated from the global configuration variables. . Create and apply a merge patch . Given both an original JSON document and a modified JSON document, you can create a Merge Patch (https://tools.ietf.org/html/rfc7396) document. . It can describe the changes needed to convert from the original to the modified JSON document. . Once you have a merge patch, you can apply it to other JSON documents using the jsonpatch.MergePatch(document, patch) function. . package main . import ( "fmt" . jsonpatch "github.com/evanphx/json-patch" ) . func main() { // Let's create a merge patch from these two documents... original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) target := []byte(`{"name": "Jane", "age": 24}`) . patch, err := jsonpatch.CreateMergePatch(original, target) if err != nil { panic(err) } . // Now lets apply the patch against a different JSON document... . alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`) modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch) . fmt.Printf("patch document: %s\n", patch) fmt.Printf("updated alternative doc: %s\n", modifiedAlternative) } . When ran, you get the following output: . $ go run main.go patch document: {"height":null,"name":"Jane"} updated alternative doc: {"age":28,"name":"Jane"} . Create and apply a JSON Patch . You can create patch objects using DecodePatch([]byte), which can then be applied against JSON documents. . The following is an example of creating a patch from two operations, and applying it against a JSON document. . package main . import ( "fmt" . jsonpatch "github.com/evanphx/json-patch" ) . func main() { original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) patchJSON := []byte(`[ {"op": "replace", "path": "/name", "value": "Jane"}, {"op": "remove", "path": "/height"} ]`) . patch, err := jsonpatch.DecodePatch(patchJSON) if err != nil { panic(err) } . modified, err := patch.Apply(original) if err != nil { panic(err) } . fmt.Printf("Original document: %s\n", original) fmt.Printf("Modified document: %s\n", modified) } . When ran, you get the following output: . $ go run main.go Original document: {"name": "John", "age": 24, "height": 3.21} Modified document: {"age":24,"name":"Jane"} . Comparing JSON documents . Due to potential whitespace and ordering differences, one cannot simply compare JSON strings or byte-arrays directly. . As such, you can instead use jsonpatch.Equal(document1, document2) to determine if two JSON documents are *structurally* equal. This ignores whitespace differences, and key-value ordering. . package main . import ( "fmt" . jsonpatch "github.com/evanphx/json-patch" ) . func main() { original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) similar := []byte(` { "age": 24, "height": 3.21, "name": "John" } `) different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`) . if jsonpatch.Equal(original, similar) { fmt.Println(`"original" is structurally equal to "similar"`) } . if !jsonpatch.Equal(original, different) { fmt.Println(`"original" is _not_ structurally equal to "different"`) } } . When ran, you get the following output: . $ go run main.go "original" is structurally equal to "similar" "original" is _not_ structurally equal to "different" . Combine merge patches . Given two JSON merge patch documents, it is possible to combine them into a single merge patch which can describe both set of changes. . The resulting merge patch can be used such that applying it results in a document structurally similar as merging each merge patch to the document in succession. . package main . import ( "fmt" . jsonpatch "github.com/evanphx/json-patch" ) . func main() { original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) . nameAndHeight := []byte(`{"height":null,"name":"Jane"}`) ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`) . // Let's combine these merge patch documents... combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes) if err != nil { panic(err) } . // Apply each patch individual against the original document withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight) if err != nil { panic(err) } . withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes) if err != nil { panic(err) } . // Apply the combined patch against the original document . withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch) if err != nil { panic(err) } . // Do both result in the same thing? They should! if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) { fmt.Println("Both JSON documents are structurally the same!") } . fmt.Printf("combined merge patch: %s", combinedPatch) } . When ran, you get the following output: . $ go run main.go Both JSON documents are structurally the same! combined merge patch: {"age":4.23,"eyes":"blue","height":null, "name":"Jane"} . CLI for comparing JSON documents . You can install the commandline program json-patch. . This program can take multiple JSON patch documents as arguments, and fed a JSON document from stdin. It will apply the patch(es) against the document and output the modified doc. . **patch.1.json** . [ {"op": "replace", "path": "/name", "value": "Jane"}, {"op": "remove", "path": "/height"} ] . **patch.2.json** . [ {"op": "add", "path": "/address", "value": "123 Main St"}, {"op": "replace", "path": "/age", "value": "21"} ] . **document.json** . { "name": "John", "age": 24, "height": 3.21 } . You can then run: . $ go install github.com/evanphx/json-patch/cmd/json-patch $ cat document.json | json-patch -p patch.1.json -p patch.2.json {"address":"123 Main St","age":"21","name":"Jane"} . Help It! . Contributions are welcomed! Leave an issue (https://github.com/evanphx/json-patch/issues) or create a PR (https://github.com/evanphx/json-patch/compare). . Before creating a pull request, we'd ask that you make sure tests are passing and that you have added new tests when applicable. . Contributors can run tests using: . go test -cover ./... . Builds for pull requests are tested automatically using GitHub Actions (https://github.com/evanphx/json-patch/actions/workflows/go.yml). This is a build dependency of apiextensions-apiserver, wich I intend to package for k9s.

