update json-patch to fix nil value issue when creating mergepatch

This commit is contained in:
Di Xu
2017-07-20 10:48:18 +08:00
parent 3f887171dd
commit 8447cee0e0
9 changed files with 75 additions and 37 deletions

View File

@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"reflect"
"strings"
)
func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
@@ -28,7 +27,6 @@ func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
for k, v := range *patch {
k := decodePatchKey(k)
if v == nil {
if mergeMerge {
(*doc)[k] = nil
@@ -226,6 +224,9 @@ func matchesValue(av, bv interface{}) bool {
if bt == at {
return true
}
case nil:
// Both nil, fine.
return true
case map[string]interface{}:
bt := bv.(map[string]interface{})
for key := range at {
@@ -250,16 +251,15 @@ func matchesValue(av, bv interface{}) bool {
func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
into := map[string]interface{}{}
for key, bv := range b {
escapedKey := encodePatchKey(key)
av, ok := a[key]
// value was added
if !ok {
into[escapedKey] = bv
into[key] = bv
continue
}
// If types have changed, replace completely
if reflect.TypeOf(av) != reflect.TypeOf(bv) {
into[escapedKey] = bv
into[key] = bv
continue
}
// Types are the same, compare values
@@ -272,23 +272,23 @@ func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
return nil, err
}
if len(dst) > 0 {
into[escapedKey] = dst
into[key] = dst
}
case string, float64, bool:
if !matchesValue(av, bv) {
into[escapedKey] = bv
into[key] = bv
}
case []interface{}:
bt := bv.([]interface{})
if !matchesArray(at, bt) {
into[escapedKey] = bv
into[key] = bv
}
case nil:
switch bv.(type) {
case nil:
// Both nil, fine.
default:
into[escapedKey] = bv
into[key] = bv
}
default:
panic(fmt.Sprintf("Unknown type:%T in key %s", av, key))
@@ -303,23 +303,3 @@ func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
}
return into, nil
}
// From http://tools.ietf.org/html/rfc6901#section-4 :
//
// Evaluation of each reference token begins by decoding any escaped
// character sequence. This is performed by first transforming any
// occurrence of the sequence '~1' to '/', and then transforming any
// occurrence of the sequence '~0' to '~'.
var (
rfc6901Encoder = strings.NewReplacer("~", "~0", "/", "~1")
rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
)
func decodePatchKey(k string) string {
return rfc6901Decoder.Replace(k)
}
func encodePatchKey(k string) string {
return rfc6901Encoder.Replace(k)
}