merge.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package jsonpatch
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "reflect"
  6. )
  7. func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
  8. curDoc, err := cur.intoDoc()
  9. if err != nil {
  10. pruneNulls(patch)
  11. return patch
  12. }
  13. patchDoc, err := patch.intoDoc()
  14. if err != nil {
  15. return patch
  16. }
  17. mergeDocs(curDoc, patchDoc, mergeMerge)
  18. return cur
  19. }
  20. func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
  21. for k, v := range *patch {
  22. if v == nil {
  23. if mergeMerge {
  24. (*doc)[k] = nil
  25. } else {
  26. delete(*doc, k)
  27. }
  28. } else {
  29. cur, ok := (*doc)[k]
  30. if !ok || cur == nil {
  31. pruneNulls(v)
  32. (*doc)[k] = v
  33. } else {
  34. (*doc)[k] = merge(cur, v, mergeMerge)
  35. }
  36. }
  37. }
  38. }
  39. func pruneNulls(n *lazyNode) {
  40. sub, err := n.intoDoc()
  41. if err == nil {
  42. pruneDocNulls(sub)
  43. } else {
  44. ary, err := n.intoAry()
  45. if err == nil {
  46. pruneAryNulls(ary)
  47. }
  48. }
  49. }
  50. func pruneDocNulls(doc *partialDoc) *partialDoc {
  51. for k, v := range *doc {
  52. if v == nil {
  53. delete(*doc, k)
  54. } else {
  55. pruneNulls(v)
  56. }
  57. }
  58. return doc
  59. }
  60. func pruneAryNulls(ary *partialArray) *partialArray {
  61. newAry := []*lazyNode{}
  62. for _, v := range *ary {
  63. if v != nil {
  64. pruneNulls(v)
  65. newAry = append(newAry, v)
  66. }
  67. }
  68. *ary = newAry
  69. return ary
  70. }
  71. var errBadJSONDoc = fmt.Errorf("Invalid JSON Document")
  72. var errBadJSONPatch = fmt.Errorf("Invalid JSON Patch")
  73. // MergeMergePatches merges two merge patches together, such that
  74. // applying this resulting merged merge patch to a document yields the same
  75. // as merging each merge patch to the document in succession.
  76. func MergeMergePatches(patch1Data, patch2Data []byte) ([]byte, error) {
  77. return doMergePatch(patch1Data, patch2Data, true)
  78. }
  79. // MergePatch merges the patchData into the docData.
  80. func MergePatch(docData, patchData []byte) ([]byte, error) {
  81. return doMergePatch(docData, patchData, false)
  82. }
  83. func doMergePatch(docData, patchData []byte, mergeMerge bool) ([]byte, error) {
  84. doc := &partialDoc{}
  85. docErr := json.Unmarshal(docData, doc)
  86. patch := &partialDoc{}
  87. patchErr := json.Unmarshal(patchData, patch)
  88. if _, ok := docErr.(*json.SyntaxError); ok {
  89. return nil, errBadJSONDoc
  90. }
  91. if _, ok := patchErr.(*json.SyntaxError); ok {
  92. return nil, errBadJSONPatch
  93. }
  94. if docErr == nil && *doc == nil {
  95. return nil, errBadJSONDoc
  96. }
  97. if patchErr == nil && *patch == nil {
  98. return nil, errBadJSONPatch
  99. }
  100. if docErr != nil || patchErr != nil {
  101. // Not an error, just not a doc, so we turn straight into the patch
  102. if patchErr == nil {
  103. if mergeMerge {
  104. doc = patch
  105. } else {
  106. doc = pruneDocNulls(patch)
  107. }
  108. } else {
  109. patchAry := &partialArray{}
  110. patchErr = json.Unmarshal(patchData, patchAry)
  111. if patchErr != nil {
  112. return nil, errBadJSONPatch
  113. }
  114. pruneAryNulls(patchAry)
  115. out, patchErr := json.Marshal(patchAry)
  116. if patchErr != nil {
  117. return nil, errBadJSONPatch
  118. }
  119. return out, nil
  120. }
  121. } else {
  122. mergeDocs(doc, patch, mergeMerge)
  123. }
  124. return json.Marshal(doc)
  125. }
  126. // CreateMergePatch creates a merge patch as specified in http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07
  127. //
  128. // 'a' is original, 'b' is the modified document. Both are to be given as json encoded content.
  129. // The function will return a mergeable json document with differences from a to b.
  130. //
  131. // An error will be returned if any of the two documents are invalid.
  132. func CreateMergePatch(a, b []byte) ([]byte, error) {
  133. aI := map[string]interface{}{}
  134. bI := map[string]interface{}{}
  135. err := json.Unmarshal(a, &aI)
  136. if err != nil {
  137. return nil, errBadJSONDoc
  138. }
  139. err = json.Unmarshal(b, &bI)
  140. if err != nil {
  141. return nil, errBadJSONDoc
  142. }
  143. dest, err := getDiff(aI, bI)
  144. if err != nil {
  145. return nil, err
  146. }
  147. return json.Marshal(dest)
  148. }
  149. // Returns true if the array matches (must be json types).
  150. // As is idiomatic for go, an empty array is not the same as a nil array.
  151. func matchesArray(a, b []interface{}) bool {
  152. if len(a) != len(b) {
  153. return false
  154. }
  155. if (a == nil && b != nil) || (a != nil && b == nil) {
  156. return false
  157. }
  158. for i := range a {
  159. if !matchesValue(a[i], b[i]) {
  160. return false
  161. }
  162. }
  163. return true
  164. }
  165. // Returns true if the values matches (must be json types)
  166. // The types of the values must match, otherwise it will always return false
  167. // If two map[string]interface{} are given, all elements must match.
  168. func matchesValue(av, bv interface{}) bool {
  169. if reflect.TypeOf(av) != reflect.TypeOf(bv) {
  170. return false
  171. }
  172. switch at := av.(type) {
  173. case string:
  174. bt := bv.(string)
  175. if bt == at {
  176. return true
  177. }
  178. case float64:
  179. bt := bv.(float64)
  180. if bt == at {
  181. return true
  182. }
  183. case bool:
  184. bt := bv.(bool)
  185. if bt == at {
  186. return true
  187. }
  188. case nil:
  189. // Both nil, fine.
  190. return true
  191. case map[string]interface{}:
  192. bt := bv.(map[string]interface{})
  193. for key := range at {
  194. if !matchesValue(at[key], bt[key]) {
  195. return false
  196. }
  197. }
  198. for key := range bt {
  199. if !matchesValue(at[key], bt[key]) {
  200. return false
  201. }
  202. }
  203. return true
  204. case []interface{}:
  205. bt := bv.([]interface{})
  206. return matchesArray(at, bt)
  207. }
  208. return false
  209. }
  210. // getDiff returns the (recursive) difference between a and b as a map[string]interface{}.
  211. func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
  212. into := map[string]interface{}{}
  213. for key, bv := range b {
  214. av, ok := a[key]
  215. // value was added
  216. if !ok {
  217. into[key] = bv
  218. continue
  219. }
  220. // If types have changed, replace completely
  221. if reflect.TypeOf(av) != reflect.TypeOf(bv) {
  222. into[key] = bv
  223. continue
  224. }
  225. // Types are the same, compare values
  226. switch at := av.(type) {
  227. case map[string]interface{}:
  228. bt := bv.(map[string]interface{})
  229. dst := make(map[string]interface{}, len(bt))
  230. dst, err := getDiff(at, bt)
  231. if err != nil {
  232. return nil, err
  233. }
  234. if len(dst) > 0 {
  235. into[key] = dst
  236. }
  237. case string, float64, bool:
  238. if !matchesValue(av, bv) {
  239. into[key] = bv
  240. }
  241. case []interface{}:
  242. bt := bv.([]interface{})
  243. if !matchesArray(at, bt) {
  244. into[key] = bv
  245. }
  246. case nil:
  247. switch bv.(type) {
  248. case nil:
  249. // Both nil, fine.
  250. default:
  251. into[key] = bv
  252. }
  253. default:
  254. panic(fmt.Sprintf("Unknown type:%T in key %s", av, key))
  255. }
  256. }
  257. // Now add all deleted values as nil
  258. for key := range a {
  259. _, found := b[key]
  260. if !found {
  261. into[key] = nil
  262. }
  263. }
  264. return into, nil
  265. }