merge.go 8.6 KB

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