-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
define ApplyJSONPatch helper, add tests
- Loading branch information
1 parent
fd0e3dd
commit 90081b5
Showing
3 changed files
with
132 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
} |