Jsonpatch
jsonpatch is a Go library to create JSON patches (RFC6902) directly from arbitrary Go objects and facilitates the implementation of sophisticated custom (e.g. filtered, validated) patch creation.
Install / Use
/learn @snorwin/JsonpatchREADME
jsonpatch
jsonpatch is a Go library to create JSON patches (RFC6902) directly from arbitrary Go objects and facilitates the implementation of sophisticated custom (e.g. filtered, validated) patch creation.
Basic Example
package main
import (
"fmt"
"github.com/snorwin/jsonpatch"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
original := &Person{
Name: "John Doe",
Age: 42,
}
updated := &Person{
Name: "Jane Doe",
Age: 21,
}
patch, _ := jsonpatch.CreateJSONPatch(updated, original)
fmt.Println(patch.String())
}
[{"op":"replace","path":"/name","value":"Jane Doe"},{"op":"replace","path":"/age","value":21}]
Options
Filter patches using Predicates
The option WithPredicate sets a patch Predicate which can be used to filter or validate the patch creation.
For each kind of patch (add, remove and replace) a dedicated filter function can be configured. The
predicate will be checked before a patch is created, or the JSON object is processed further.
Example
package main
import (
"fmt"
"github.com/snorwin/jsonpatch"
)
type Job struct {
Position string `json:"position"`
Company string `json:"company"`
Volunteer bool `json:"volunteer"`
}
func main() {
original := []Job{
{Position: "IT Trainer", Company: "Powercoders", Volunteer: true},
{Position: "Software Engineer", Company: "Github"},
}
updated := []Job{
{Position: "Senior IT Trainer", Company: "Powercoders", Volunteer: true},
{Position: "Senior Software Engineer", Company: "Github"},
}
patch, _ := jsonpatch.CreateJSONPatch(updated, original, jsonpatch.WithPredicate(jsonpatch.Funcs{
ReplaceFunc: func(pointer jsonpatch.JSONPointer, value, _ interface{}) bool {
// only update volunteering jobs
if job, ok := value.(Job); ok {
return job.Volunteer
}
return true
},
}))
fmt.Println(patch.String())
}
[{"op":"replace","path":"/0/position","value":"Senior IT Trainer"}]
Create partial patches
The option WithPrefix is used to specify a JSON pointer prefix if only a sub part of JSON structure needs to be patched,
but the patch still need to be applied on the entire JSON object.
Example
package main
import (
"fmt"
"github.com/snorwin/jsonpatch"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Jobs []Job `json:"jobs"`
}
type Job struct {
Position string `json:"position"`
Company string `json:"company"`
Volunteer bool `json:"volunteer"`
}
func main() {
original := &Person{
Name: "John Doe",
Age: 42,
Jobs: []Job{{Position: "IT Trainer", Company: "Powercoders"}},
}
updated := []Job{
{Position: "Senior IT Trainer", Company: "Powercoders", Volunteer: true},
{Position: "Software Engineer", Company: "Github"},
}
patch, _ := jsonpatch.CreateJSONPatch(updated, original.Jobs, jsonpatch.WithPrefix(jsonpatch.ParseJSONPointer("/jobs")))
fmt.Println(patch.String())
}
[{"op":"replace","path":"/jobs/0/position","value":"Senior IT Trainer"},{"op":"replace","path":"/jobs/0/volunteer","value":true},{"op":"add","path":"/jobs/1","value":{"position":"Software Engineer","company":"Github","volunteer":false}}]
Ignore slice order
There are two options to ignore the slice order:
IgnoreSliceOrderwill ignore the order of all slices of built-in types (e.g.int,string) during the patch creation and will instead use the value itself in order to match and compare the current and modified JSON.IgnoreSliceOrderWithPatternallows to specify for which slices the order should be ignored using JSONPointer patterns (e.g./jobs,/jobs/*). Furthermore, the slice order of structs (and pointer of structs) slices can be ignored by specifying a JSON field which should be used to match the struct values.
NOTE: Ignoring the slice order only works if the elements (or the values used to match structs) are unique
Example
package main
import (
"fmt"
"github.com/snorwin/jsonpatch"
)
type Person struct {
Name string `json:"name"`
Pseudonyms []string `json:"pseudonyms"`
Jobs []Job `json:"jobs"`
}
type Job struct {
Position string `json:"position"`
Company string `json:"company"`
Volunteer bool `json:"volunteer"`
}
func main() {
original := Person{
Name: "John Doe",
Pseudonyms: []string{"Jo", "JayD"},
Jobs: []Job{
{Position: "Software Engineer", Company: "Github"},
{Position: "IT Trainer", Company: "Powercoders"},
},
}
updated := Person{
Name: "John Doe",
Pseudonyms: []string{"Jonny", "Jo"},
Jobs: []Job{
{Position: "IT Trainer", Company: "Powercoders", Volunteer: true},
{Position: "Senior Software Engineer", Company: "Github"},
},
}
patch, _ := jsonpatch.CreateJSONPatch(updated, original,
jsonpatch.IgnoreSliceOrderWithPattern([]jsonpatch.IgnorePattern{{Pattern: "/*", JSONField: "company"}}),
jsonpatch.IgnoreSliceOrder(),
)
fmt.Println(patch.String())
}
[{"op":"add","path":"/pseudonyms/2","value":"Jonny"},{"op":"remove","path":"/pseudonyms/1"},{"op":"replace","path":"/jobs/1/volunteer","value":true},{"op":"replace","path":"/jobs/0/position","value":"Senior Software Engineer"}]
Related Skills
node-connect
338.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.6kCommit, push, and open a PR
