{"id":37086357,"url":"https://github.com/tilt-dev/json-patch","last_synced_at":"2026-01-14T10:37:28.796Z","repository":{"id":57519699,"uuid":"249754231","full_name":"tilt-dev/json-patch","owner":"tilt-dev","description":"A Go library to apply RFC6902 patches and create and apply RFC7386 patches","archived":true,"fork":true,"pushed_at":"2020-05-15T13:52:53.000Z","size":149,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-13T18:18:45.702Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"evanphx/json-patch","license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tilt-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-24T16:05:25.000Z","updated_at":"2023-01-28T03:54:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tilt-dev/json-patch","commit_stats":null,"previous_names":["windmilleng/json-patch"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/tilt-dev/json-patch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tilt-dev%2Fjson-patch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tilt-dev%2Fjson-patch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tilt-dev%2Fjson-patch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tilt-dev%2Fjson-patch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tilt-dev","download_url":"https://codeload.github.com/tilt-dev/json-patch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tilt-dev%2Fjson-patch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28417670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:25:19.714Z","status":"ssl_error","status_checked_at":"2026-01-14T10:22:49.371Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-01-14T10:37:28.035Z","updated_at":"2026-01-14T10:37:28.789Z","avatar_url":"https://github.com/tilt-dev.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JSON-Patch\n`jsonpatch` is a library which provides functionality for both applying\n[RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as\nwell as for calculating \u0026 applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).\n\n[![GoDoc](https://godoc.org/github.com/evanphx/json-patch?status.svg)](http://godoc.org/github.com/evanphx/json-patch)\n[![Build Status](https://travis-ci.org/evanphx/json-patch.svg?branch=master)](https://travis-ci.org/evanphx/json-patch)\n[![Report Card](https://goreportcard.com/badge/github.com/evanphx/json-patch)](https://goreportcard.com/report/github.com/evanphx/json-patch)\n\n# Get It!\n\n**Latest and greatest**: \n```bash\ngo get -u github.com/evanphx/json-patch\n```\n\n**Stable Versions**:\n* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`\n\n(previous versions below `v3` are unavailable)\n\n# Use It!\n* [Create and apply a merge patch](#create-and-apply-a-merge-patch)\n* [Create and apply a JSON Patch](#create-and-apply-a-json-patch)\n* [Comparing JSON documents](#comparing-json-documents)\n* [Combine merge patches](#combine-merge-patches)\n\n\n# Configuration\n\n* There is a global configuration variable `jsonpatch.SupportNegativeIndices`.\n  This defaults to `true` and enables the non-standard practice of allowing\n  negative indices to mean indices starting at the end of an array. This\n  functionality can be disabled by setting `jsonpatch.SupportNegativeIndices =\n  false`.\n\n* There is a global configuration variable `jsonpatch.AccumulatedCopySizeLimit`,\n  which limits the total size increase in bytes caused by \"copy\" operations in a\n  patch. It defaults to 0, which means there is no limit.\n\n## Create and apply a merge patch\nGiven both an original JSON document and a modified JSON document, you can create\na [Merge Patch](https://tools.ietf.org/html/rfc7396) document. \n\nIt can describe the changes needed to convert from the original to the \nmodified JSON document.\n\nOnce you have a merge patch, you can apply it to other JSON documents using the\n`jsonpatch.MergePatch(document, patch)` function.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\tjsonpatch \"github.com/evanphx/json-patch\"\n)\n\nfunc main() {\n\t// Let's create a merge patch from these two documents...\n\toriginal := []byte(`{\"name\": \"John\", \"age\": 24, \"height\": 3.21}`)\n\ttarget := []byte(`{\"name\": \"Jane\", \"age\": 24}`)\n\n\tpatch, err := jsonpatch.CreateMergePatch(original, target)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Now lets apply the patch against a different JSON document...\n\n\talternative := []byte(`{\"name\": \"Tina\", \"age\": 28, \"height\": 3.75}`)\n\tmodifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)\n\n\tfmt.Printf(\"patch document:   %s\\n\", patch)\n\tfmt.Printf(\"updated alternative doc: %s\\n\", modifiedAlternative)\n}\n```\n\nWhen ran, you get the following output:\n\n```bash\n$ go run main.go\npatch document:   {\"height\":null,\"name\":\"Jane\"}\nupdated tina doc: {\"age\":28,\"name\":\"Jane\"}\n```\n\n## Create and apply a JSON Patch\nYou can create patch objects using `DecodePatch([]byte)`, which can then \nbe applied against JSON documents.\n\nThe following is an example of creating a patch from two operations, and\napplying it against a JSON document.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\tjsonpatch \"github.com/evanphx/json-patch\"\n)\n\nfunc main() {\n\toriginal := []byte(`{\"name\": \"John\", \"age\": 24, \"height\": 3.21}`)\n\tpatchJSON := []byte(`[\n\t\t{\"op\": \"replace\", \"path\": \"/name\", \"value\": \"Jane\"},\n\t\t{\"op\": \"remove\", \"path\": \"/height\"}\n\t]`)\n\n\tpatch, err := jsonpatch.DecodePatch(patchJSON)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tmodified, err := patch.Apply(original)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Printf(\"Original document: %s\\n\", original)\n\tfmt.Printf(\"Modified document: %s\\n\", modified)\n}\n```\n\nWhen ran, you get the following output:\n\n```bash\n$ go run main.go\nOriginal document: {\"name\": \"John\", \"age\": 24, \"height\": 3.21}\nModified document: {\"age\":24,\"name\":\"Jane\"}\n```\n\n## Comparing JSON documents\nDue to potential whitespace and ordering differences, one cannot simply compare\nJSON strings or byte-arrays directly. \n\nAs such, you can instead use `jsonpatch.Equal(document1, document2)` to \ndetermine if two JSON documents are _structurally_ equal. This ignores\nwhitespace differences, and key-value ordering.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\tjsonpatch \"github.com/evanphx/json-patch\"\n)\n\nfunc main() {\n\toriginal := []byte(`{\"name\": \"John\", \"age\": 24, \"height\": 3.21}`)\n\tsimilar := []byte(`\n\t\t{\n\t\t\t\"age\": 24,\n\t\t\t\"height\": 3.21,\n\t\t\t\"name\": \"John\"\n\t\t}\n\t`)\n\tdifferent := []byte(`{\"name\": \"Jane\", \"age\": 20, \"height\": 3.37}`)\n\n\tif jsonpatch.Equal(original, similar) {\n\t\tfmt.Println(`\"original\" is structurally equal to \"similar\"`)\n\t}\n\n\tif !jsonpatch.Equal(original, different) {\n\t\tfmt.Println(`\"original\" is _not_ structurally equal to \"different\"`)\n\t}\n}\n```\n\nWhen ran, you get the following output:\n```bash\n$ go run main.go\n\"original\" is structurally equal to \"similar\"\n\"original\" is _not_ structurally equal to \"different\"\n```\n\n## Combine merge patches\nGiven two JSON merge patch documents, it is possible to combine them into a \nsingle merge patch which can describe both set of changes.\n\nThe resulting merge patch can be used such that applying it results in a\ndocument structurally similar as merging each merge patch to the document\nin succession. \n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\tjsonpatch \"github.com/evanphx/json-patch\"\n)\n\nfunc main() {\n\toriginal := []byte(`{\"name\": \"John\", \"age\": 24, \"height\": 3.21}`)\n\n\tnameAndHeight := []byte(`{\"height\":null,\"name\":\"Jane\"}`)\n\tageAndEyes := []byte(`{\"age\":4.23,\"eyes\":\"blue\"}`)\n\n\t// Let's combine these merge patch documents...\n\tcombinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Apply each patch individual against the original document\n\twithoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\twithoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Apply the combined patch against the original document\n\n\twithCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Do both result in the same thing? They should!\n\tif jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {\n\t\tfmt.Println(\"Both JSON documents are structurally the same!\")\n\t}\n\n\tfmt.Printf(\"combined merge patch: %s\", combinedPatch)\n}\n```\n\nWhen ran, you get the following output:\n```bash\n$ go run main.go\nBoth JSON documents are structurally the same!\ncombined merge patch: {\"age\":4.23,\"eyes\":\"blue\",\"height\":null,\"name\":\"Jane\"}\n```\n\n# CLI for comparing JSON documents\nYou can install the commandline program `json-patch`.\n\nThis program can take multiple JSON patch documents as arguments, \nand fed a JSON document from `stdin`. It will apply the patch(es) against \nthe document and output the modified doc.\n\n**patch.1.json**\n```json\n[\n    {\"op\": \"replace\", \"path\": \"/name\", \"value\": \"Jane\"},\n    {\"op\": \"remove\", \"path\": \"/height\"}\n]\n```\n\n**patch.2.json**\n```json\n[\n    {\"op\": \"add\", \"path\": \"/address\", \"value\": \"123 Main St\"},\n    {\"op\": \"replace\", \"path\": \"/age\", \"value\": \"21\"}\n]\n```\n\n**document.json**\n```json\n{\n    \"name\": \"John\",\n    \"age\": 24,\n    \"height\": 3.21\n}\n```\n\nYou can then run:\n\n```bash\n$ go install github.com/evanphx/json-patch/cmd/json-patch\n$ cat document.json | json-patch -p patch.1.json -p patch.2.json\n{\"address\":\"123 Main St\",\"age\":\"21\",\"name\":\"Jane\"}\n```\n\n# Help It!\nContributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues)\nor [create a PR](https://github.com/evanphx/json-patch/compare).\n\n\nBefore creating a pull request, we'd ask that you make sure tests are passing\nand that you have added new tests when applicable.\n\nContributors can run tests using:\n\n```bash\ngo test -cover ./...\n```\n\nBuilds for pull requests are tested automatically \nusing [TravisCI](https://travis-ci.org/evanphx/json-patch).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftilt-dev%2Fjson-patch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftilt-dev%2Fjson-patch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftilt-dev%2Fjson-patch/lists"}