merge.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. package jsonpatch
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "reflect"
  7. )
  8. func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
  9. curDoc, err := cur.intoDoc()
  10. if err != nil {
  11. pruneNulls(patch)
  12. return patch
  13. }
  14. patchDoc, err := patch.intoDoc()
  15. if err != nil {
  16. return patch
  17. }
  18. mergeDocs(curDoc, patchDoc, mergeMerge)
  19. return cur
  20. }
  21. func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
  22. for k, v := range *patch {
  23. if v == nil {
  24. if mergeMerge {
  25. (*doc)[k] = nil
  26. } else {
  27. delete(*doc, k)
  28. }
  29. } else {
  30. cur, ok := (*doc)[k]
  31. if !ok || cur == nil {
  32. if !mergeMerge {
  33. pruneNulls(v)
  34. }
  35. (*doc)[k] = v
  36. } else {
  37. (*doc)[k] = merge(cur, v, mergeMerge)
  38. }
  39. }
  40. }
  41. }
  42. func pruneNulls(n *lazyNode) {
  43. sub, err := n.intoDoc()
  44. if err == nil {
  45. pruneDocNulls(sub)
  46. } else {
  47. ary, err := n.intoAry()
  48. if err == nil {
  49. pruneAryNulls(ary)
  50. }
  51. }
  52. }
  53. func pruneDocNulls(doc *partialDoc) *partialDoc {
  54. for k, v := range *doc {
  55. if v == nil {
  56. delete(*doc, k)
  57. } else {
  58. pruneNulls(v)
  59. }
  60. }
  61. return doc
  62. }
  63. func pruneAryNulls(ary *partialArray) *partialArray {
  64. newAry := []*lazyNode{}
  65. for _, v := range *ary {
  66. if v != nil {
  67. pruneNulls(v)
  68. }
  69. newAry = append(newAry, v)
  70. }
  71. *ary = newAry
  72. return ary
  73. }
  74. var ErrBadJSONDoc = fmt.Errorf("Invalid JSON Document")
  75. var ErrBadJSONPatch = fmt.Errorf("Invalid JSON Patch")
  76. var errBadMergeTypes = fmt.Errorf("Mismatched JSON Documents")
  77. // MergeMergePatches merges two merge patches together, such that
  78. // applying this resulting merged merge patch to a document yields the same
  79. // as merging each merge patch to the document in succession.
  80. func MergeMergePatches(patch1Data, patch2Data []byte) ([]byte, error) {
  81. return doMergePatch(patch1Data, patch2Data, true)
  82. }
  83. // MergePatch merges the patchData into the docData.
  84. func MergePatch(docData, patchData []byte) ([]byte, error) {
  85. return doMergePatch(docData, patchData, false)
  86. }
  87. func doMergePatch(docData, patchData []byte, mergeMerge bool) ([]byte, error) {
  88. doc := &partialDoc{}
  89. docErr := json.Unmarshal(docData, doc)
  90. patch := &partialDoc{}
  91. patchErr := json.Unmarshal(patchData, patch)
  92. if _, ok := docErr.(*json.SyntaxError); ok {
  93. return nil, ErrBadJSONDoc
  94. }
  95. if _, ok := patchErr.(*json.SyntaxError); ok {
  96. return nil, ErrBadJSONPatch
  97. }
  98. if docErr == nil && *doc == nil {
  99. return nil, ErrBadJSONDoc
  100. }
  101. if patchErr == nil && *patch == nil {
  102. return nil, ErrBadJSONPatch
  103. }
  104. if docErr != nil || patchErr != nil {
  105. // Not an error, just not a doc, so we turn straight into the patch
  106. if patchErr == nil {
  107. if mergeMerge {
  108. doc = patch
  109. } else {
  110. doc = pruneDocNulls(patch)
  111. }
  112. } else {
  113. patchAry := &partialArray{}
  114. patchErr = json.Unmarshal(patchData, patchAry)
  115. if patchErr != nil {
  116. return nil, ErrBadJSONPatch
  117. }
  118. pruneAryNulls(patchAry)
  119. out, patchErr := json.Marshal(patchAry)
  120. if patchErr != nil {
  121. return nil, ErrBadJSONPatch
  122. }
  123. return out, nil
  124. }
  125. } else {
  126. mergeDocs(doc, patch, mergeMerge)
  127. }
  128. return json.Marshal(doc)
  129. }
  130. // resemblesJSONArray indicates whether the byte-slice "appears" to be
  131. // a JSON array or not.
  132. // False-positives are possible, as this function does not check the internal
  133. // structure of the array. It only checks that the outer syntax is present and
  134. // correct.
  135. func resemblesJSONArray(input []byte) bool {
  136. input = bytes.TrimSpace(input)
  137. hasPrefix := bytes.HasPrefix(input, []byte("["))
  138. hasSuffix := bytes.HasSuffix(input, []byte("]"))
  139. return hasPrefix && hasSuffix
  140. }
  141. // CreateMergePatch will return a merge patch document capable of converting
  142. // the original document(s) to the modified document(s).
  143. // The parameters can be bytes of either two JSON Documents, or two arrays of
  144. // JSON documents.
  145. // The merge patch returned follows the specification defined at http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07
  146. func CreateMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
  147. originalResemblesArray := resemblesJSONArray(originalJSON)
  148. modifiedResemblesArray := resemblesJSONArray(modifiedJSON)
  149. // Do both byte-slices seem like JSON arrays?
  150. if originalResemblesArray && modifiedResemblesArray {
  151. return createArrayMergePatch(originalJSON, modifiedJSON)
  152. }
  153. // Are both byte-slices are not arrays? Then they are likely JSON objects...
  154. if !originalResemblesArray && !modifiedResemblesArray {
  155. return createObjectMergePatch(originalJSON, modifiedJSON)
  156. }
  157. // None of the above? Then return an error because of mismatched types.
  158. return nil, errBadMergeTypes
  159. }
  160. // createObjectMergePatch will return a merge-patch document capable of
  161. // converting the original document to the modified document.
  162. func createObjectMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
  163. originalDoc := map[string]interface{}{}
  164. modifiedDoc := map[string]interface{}{}
  165. err := json.Unmarshal(originalJSON, &originalDoc)
  166. if err != nil {
  167. return nil, ErrBadJSONDoc
  168. }
  169. err = json.Unmarshal(modifiedJSON, &modifiedDoc)
  170. if err != nil {
  171. return nil, ErrBadJSONDoc
  172. }
  173. dest, err := getDiff(originalDoc, modifiedDoc)
  174. if err != nil {
  175. return nil, err
  176. }
  177. return json.Marshal(dest)
  178. }
  179. // createArrayMergePatch will return an array of merge-patch documents capable
  180. // of converting the original document to the modified document for each
  181. // pair of JSON documents provided in the arrays.
  182. // Arrays of mismatched sizes will result in an error.
  183. func createArrayMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
  184. originalDocs := []json.RawMessage{}
  185. modifiedDocs := []json.RawMessage{}
  186. err := json.Unmarshal(originalJSON, &originalDocs)
  187. if err != nil {
  188. return nil, ErrBadJSONDoc
  189. }
  190. err = json.Unmarshal(modifiedJSON, &modifiedDocs)
  191. if err != nil {
  192. return nil, ErrBadJSONDoc
  193. }
  194. total := len(originalDocs)
  195. if len(modifiedDocs) != total {
  196. return nil, ErrBadJSONDoc
  197. }
  198. result := []json.RawMessage{}
  199. for i := 0; i < len(originalDocs); i++ {
  200. original := originalDocs[i]
  201. modified := modifiedDocs[i]
  202. patch, err := createObjectMergePatch(original, modified)
  203. if err != nil {
  204. return nil, err
  205. }
  206. result = append(result, json.RawMessage(patch))
  207. }
  208. return json.Marshal(result)
  209. }
  210. // Returns true if the array matches (must be json types).
  211. // As is idiomatic for go, an empty array is not the same as a nil array.
  212. func matchesArray(a, b []interface{}) bool {
  213. if len(a) != len(b) {
  214. return false
  215. }
  216. if (a == nil && b != nil) || (a != nil && b == nil) {
  217. return false
  218. }
  219. for i := range a {
  220. if !matchesValue(a[i], b[i]) {
  221. return false
  222. }
  223. }
  224. return true
  225. }
  226. // Returns true if the values matches (must be json types)
  227. // The types of the values must match, otherwise it will always return false
  228. // If two map[string]interface{} are given, all elements must match.
  229. func matchesValue(av, bv interface{}) bool {
  230. if reflect.TypeOf(av) != reflect.TypeOf(bv) {
  231. return false
  232. }
  233. switch at := av.(type) {
  234. case string:
  235. bt := bv.(string)
  236. if bt == at {
  237. return true
  238. }
  239. case float64:
  240. bt := bv.(float64)
  241. if bt == at {
  242. return true
  243. }
  244. case bool:
  245. bt := bv.(bool)
  246. if bt == at {
  247. return true
  248. }
  249. case nil:
  250. // Both nil, fine.
  251. return true
  252. case map[string]interface{}:
  253. bt := bv.(map[string]interface{})
  254. if len(bt) != len(at) {
  255. return false
  256. }
  257. for key := range bt {
  258. av, aOK := at[key]
  259. bv, bOK := bt[key]
  260. if aOK != bOK {
  261. return false
  262. }
  263. if !matchesValue(av, bv) {
  264. return false
  265. }
  266. }
  267. return true
  268. case []interface{}:
  269. bt := bv.([]interface{})
  270. return matchesArray(at, bt)
  271. }
  272. return false
  273. }
  274. // getDiff returns the (recursive) difference between a and b as a map[string]interface{}.
  275. func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
  276. into := map[string]interface{}{}
  277. for key, bv := range b {
  278. av, ok := a[key]
  279. // value was added
  280. if !ok {
  281. into[key] = bv
  282. continue
  283. }
  284. // If types have changed, replace completely
  285. if reflect.TypeOf(av) != reflect.TypeOf(bv) {
  286. into[key] = bv
  287. continue
  288. }
  289. // Types are the same, compare values
  290. switch at := av.(type) {
  291. case map[string]interface{}:
  292. bt := bv.(map[string]interface{})
  293. dst := make(map[string]interface{}, len(bt))
  294. dst, err := getDiff(at, bt)
  295. if err != nil {
  296. return nil, err
  297. }
  298. if len(dst) > 0 {
  299. into[key] = dst
  300. }
  301. case string, float64, bool:
  302. if !matchesValue(av, bv) {
  303. into[key] = bv
  304. }
  305. case []interface{}:
  306. bt := bv.([]interface{})
  307. if !matchesArray(at, bt) {
  308. into[key] = bv
  309. }
  310. case nil:
  311. switch bv.(type) {
  312. case nil:
  313. // Both nil, fine.
  314. default:
  315. into[key] = bv
  316. }
  317. default:
  318. panic(fmt.Sprintf("Unknown type:%T in key %s", av, key))
  319. }
  320. }
  321. // Now add all deleted values as nil
  322. for key := range a {
  323. _, found := b[key]
  324. if !found {
  325. into[key] = nil
  326. }
  327. }
  328. return into, nil
  329. }