Skip to content

Commit

Permalink
define ApplyJSONPatch helper, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mattbonnell committed Mar 24, 2021
1 parent fd0e3dd commit 90081b5
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 19 deletions.
20 changes: 1 addition & 19 deletions client/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
"net/http"
"time"

jsonpatch "github.com/evanphx/json-patch"

"github.com/ory/x/errorsx"

"github.com/ory/herodot"
Expand Down Expand Up @@ -186,30 +184,14 @@ func (h *Handler) Patch(w http.ResponseWriter, r *http.Request, ps httprouter.Pa
return
}

patch, err := jsonpatch.DecodePatch(patchJSON)
if err != nil {
h.r.Writer().WriteError(w, r, errorsx.WithStack(err))
return
}

id := ps.ByName("id")
c, err := h.r.ClientManager().GetConcreteClient(r.Context(), id)
if err != nil {
h.r.Writer().WriteError(w, r, err)
return
}

original, err := json.Marshal(c)
if err != nil {
h.r.Writer().WriteError(w, r, err)
return
}
modified, err := patch.Apply(original)
if err != nil {
h.r.Writer().WriteError(w, r, err)
return
}
if err := json.Unmarshal(modified, c); err != nil {
if err := x.ApplyJSONPatch(patchJSON, c); err != nil {
h.r.Writer().WriteError(w, r, err)
return
}
Expand Down
29 changes: 29 additions & 0 deletions x/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package x

import (
"encoding/json"

jsonpatch "github.com/evanphx/json-patch"
)

func ApplyJSONPatch(p json.RawMessage, object interface{}) error {
patch, err := jsonpatch.DecodePatch(p)
if err != nil {
return err
}

original, err := json.Marshal(object)
if err != nil {
return err
}

modified, err := patch.Apply(original)
if err != nil {
return err
}

if err := json.Unmarshal(modified, object); err != nil {
return err
}
return nil
}
102 changes: 102 additions & 0 deletions x/json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package x

import (
"testing"

"github.com/mohae/deepcopy"
"github.com/stretchr/testify/require"
)

type TestType struct {
Field1 string
Field2 []string
Field3 struct {
Field1 bool
Field2 []int
}
}

func TestApplyJSONPatch(t *testing.T) {
object := TestType{
Field1: "foo",
Field2: []string{
"foo",
"bar",
"baz",
"kaz",
},
Field3: struct {
Field1 bool
Field2 []int
}{
Field1: true,
Field2: []int{
1,
2,
3,
},
},
}
t.Run("case=empty patch", func(t *testing.T) {
rawPatch := []byte(`[]`)
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, object, obj)
})
t.Run("case=field replace", func(t *testing.T) {
rawPatch := []byte(`[{"op": "replace", "path": "/Field1", "value": "boo"}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field1 = "boo"
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
t.Run("case=array replace", func(t *testing.T) {
rawPatch := []byte(`[{"op": "replace", "path": "/Field2/0", "value": "boo"}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field2[0] = "boo"
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
t.Run("case=array append", func(t *testing.T) {
rawPatch := []byte(`[{"op": "add", "path": "/Field2/-", "value": "boo"}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field2 = append(expected.Field2, "boo")
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
t.Run("case=array remove", func(t *testing.T) {
rawPatch := []byte(`[{"op": "remove", "path": "/Field2/0"}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field2 = expected.Field2[1:]
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
t.Run("case=nested field replace", func(t *testing.T) {
rawPatch := []byte(`[{"op": "replace", "path": "/Field3/Field1", "value": false}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field3.Field1 = false
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
t.Run("case=nested array append", func(t *testing.T) {
rawPatch := []byte(`[{"op": "add", "path": "/Field3/Field2/-", "value": 4}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field3.Field2 = append(expected.Field3.Field2, 4)
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
t.Run("case=nested array remove", func(t *testing.T) {
rawPatch := []byte(`[{"op": "remove", "path": "/Field3/Field2/2"}]`)
expected := deepcopy.Copy(object).(TestType)
expected.Field3.Field2 = expected.Field3.Field2[:2]
obj := deepcopy.Copy(object).(TestType)
require.NoError(t, ApplyJSONPatch(rawPatch, &obj))
require.Equal(t, expected, obj)
})
}

0 comments on commit 90081b5

Please sign in to comment.