patch.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. package jsonpatch
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "github.com/pkg/errors"
  9. )
  10. const (
  11. eRaw = iota
  12. eDoc
  13. eAry
  14. )
  15. var (
  16. // SupportNegativeIndices decides whether to support non-standard practice of
  17. // allowing negative indices to mean indices starting at the end of an array.
  18. // Default to true.
  19. SupportNegativeIndices bool = true
  20. // AccumulatedCopySizeLimit limits the total size increase in bytes caused by
  21. // "copy" operations in a patch.
  22. AccumulatedCopySizeLimit int64 = 0
  23. )
  24. var (
  25. ErrTestFailed = errors.New("test failed")
  26. ErrMissing = errors.New("missing value")
  27. ErrUnknownType = errors.New("unknown object type")
  28. ErrInvalid = errors.New("invalid state detected")
  29. ErrInvalidIndex = errors.New("invalid index referenced")
  30. )
  31. type lazyNode struct {
  32. raw *json.RawMessage
  33. doc partialDoc
  34. ary partialArray
  35. which int
  36. }
  37. // Operation is a single JSON-Patch step, such as a single 'add' operation.
  38. type Operation map[string]*json.RawMessage
  39. // Patch is an ordered collection of Operations.
  40. type Patch []Operation
  41. type partialDoc map[string]*lazyNode
  42. type partialArray []*lazyNode
  43. type container interface {
  44. get(key string) (*lazyNode, error)
  45. set(key string, val *lazyNode) error
  46. add(key string, val *lazyNode) error
  47. remove(key string) error
  48. }
  49. func newLazyNode(raw *json.RawMessage) *lazyNode {
  50. return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw}
  51. }
  52. func (n *lazyNode) MarshalJSON() ([]byte, error) {
  53. switch n.which {
  54. case eRaw:
  55. return json.Marshal(n.raw)
  56. case eDoc:
  57. return json.Marshal(n.doc)
  58. case eAry:
  59. return json.Marshal(n.ary)
  60. default:
  61. return nil, ErrUnknownType
  62. }
  63. }
  64. func (n *lazyNode) UnmarshalJSON(data []byte) error {
  65. dest := make(json.RawMessage, len(data))
  66. copy(dest, data)
  67. n.raw = &dest
  68. n.which = eRaw
  69. return nil
  70. }
  71. func deepCopy(src *lazyNode) (*lazyNode, int, error) {
  72. if src == nil {
  73. return nil, 0, nil
  74. }
  75. a, err := src.MarshalJSON()
  76. if err != nil {
  77. return nil, 0, err
  78. }
  79. sz := len(a)
  80. ra := make(json.RawMessage, sz)
  81. copy(ra, a)
  82. return newLazyNode(&ra), sz, nil
  83. }
  84. func (n *lazyNode) intoDoc() (*partialDoc, error) {
  85. if n.which == eDoc {
  86. return &n.doc, nil
  87. }
  88. if n.raw == nil {
  89. return nil, ErrInvalid
  90. }
  91. err := json.Unmarshal(*n.raw, &n.doc)
  92. if err != nil {
  93. return nil, err
  94. }
  95. n.which = eDoc
  96. return &n.doc, nil
  97. }
  98. func (n *lazyNode) intoAry() (*partialArray, error) {
  99. if n.which == eAry {
  100. return &n.ary, nil
  101. }
  102. if n.raw == nil {
  103. return nil, ErrInvalid
  104. }
  105. err := json.Unmarshal(*n.raw, &n.ary)
  106. if err != nil {
  107. return nil, err
  108. }
  109. n.which = eAry
  110. return &n.ary, nil
  111. }
  112. func (n *lazyNode) compact() []byte {
  113. buf := &bytes.Buffer{}
  114. if n.raw == nil {
  115. return nil
  116. }
  117. err := json.Compact(buf, *n.raw)
  118. if err != nil {
  119. return *n.raw
  120. }
  121. return buf.Bytes()
  122. }
  123. func (n *lazyNode) tryDoc() bool {
  124. if n.raw == nil {
  125. return false
  126. }
  127. err := json.Unmarshal(*n.raw, &n.doc)
  128. if err != nil {
  129. return false
  130. }
  131. n.which = eDoc
  132. return true
  133. }
  134. func (n *lazyNode) tryAry() bool {
  135. if n.raw == nil {
  136. return false
  137. }
  138. err := json.Unmarshal(*n.raw, &n.ary)
  139. if err != nil {
  140. return false
  141. }
  142. n.which = eAry
  143. return true
  144. }
  145. func (n *lazyNode) equal(o *lazyNode) bool {
  146. if n.which == eRaw {
  147. if !n.tryDoc() && !n.tryAry() {
  148. if o.which != eRaw {
  149. return false
  150. }
  151. return bytes.Equal(n.compact(), o.compact())
  152. }
  153. }
  154. if n.which == eDoc {
  155. if o.which == eRaw {
  156. if !o.tryDoc() {
  157. return false
  158. }
  159. }
  160. if o.which != eDoc {
  161. return false
  162. }
  163. if len(n.doc) != len(o.doc) {
  164. return false
  165. }
  166. for k, v := range n.doc {
  167. ov, ok := o.doc[k]
  168. if !ok {
  169. return false
  170. }
  171. if (v == nil) != (ov == nil) {
  172. return false
  173. }
  174. if v == nil && ov == nil {
  175. continue
  176. }
  177. if !v.equal(ov) {
  178. return false
  179. }
  180. }
  181. return true
  182. }
  183. if o.which != eAry && !o.tryAry() {
  184. return false
  185. }
  186. if len(n.ary) != len(o.ary) {
  187. return false
  188. }
  189. for idx, val := range n.ary {
  190. if !val.equal(o.ary[idx]) {
  191. return false
  192. }
  193. }
  194. return true
  195. }
  196. // Kind reads the "op" field of the Operation.
  197. func (o Operation) Kind() string {
  198. if obj, ok := o["op"]; ok && obj != nil {
  199. var op string
  200. err := json.Unmarshal(*obj, &op)
  201. if err != nil {
  202. return "unknown"
  203. }
  204. return op
  205. }
  206. return "unknown"
  207. }
  208. // Path reads the "path" field of the Operation.
  209. func (o Operation) Path() (string, error) {
  210. if obj, ok := o["path"]; ok && obj != nil {
  211. var op string
  212. err := json.Unmarshal(*obj, &op)
  213. if err != nil {
  214. return "unknown", err
  215. }
  216. return op, nil
  217. }
  218. return "unknown", errors.Wrapf(ErrMissing, "operation missing path field")
  219. }
  220. // From reads the "from" field of the Operation.
  221. func (o Operation) From() (string, error) {
  222. if obj, ok := o["from"]; ok && obj != nil {
  223. var op string
  224. err := json.Unmarshal(*obj, &op)
  225. if err != nil {
  226. return "unknown", err
  227. }
  228. return op, nil
  229. }
  230. return "unknown", errors.Wrapf(ErrMissing, "operation, missing from field")
  231. }
  232. func (o Operation) value() *lazyNode {
  233. if obj, ok := o["value"]; ok {
  234. return newLazyNode(obj)
  235. }
  236. return nil
  237. }
  238. // ValueInterface decodes the operation value into an interface.
  239. func (o Operation) ValueInterface() (interface{}, error) {
  240. if obj, ok := o["value"]; ok && obj != nil {
  241. var v interface{}
  242. err := json.Unmarshal(*obj, &v)
  243. if err != nil {
  244. return nil, err
  245. }
  246. return v, nil
  247. }
  248. return nil, errors.Wrapf(ErrMissing, "operation, missing value field")
  249. }
  250. func isArray(buf []byte) bool {
  251. Loop:
  252. for _, c := range buf {
  253. switch c {
  254. case ' ':
  255. case '\n':
  256. case '\t':
  257. continue
  258. case '[':
  259. return true
  260. default:
  261. break Loop
  262. }
  263. }
  264. return false
  265. }
  266. func findObject(pd *container, path string) (container, string) {
  267. doc := *pd
  268. split := strings.Split(path, "/")
  269. if len(split) < 2 {
  270. return nil, ""
  271. }
  272. parts := split[1 : len(split)-1]
  273. key := split[len(split)-1]
  274. var err error
  275. for _, part := range parts {
  276. next, ok := doc.get(decodePatchKey(part))
  277. if next == nil || ok != nil {
  278. return nil, ""
  279. }
  280. if isArray(*next.raw) {
  281. doc, err = next.intoAry()
  282. if err != nil {
  283. return nil, ""
  284. }
  285. } else {
  286. doc, err = next.intoDoc()
  287. if err != nil {
  288. return nil, ""
  289. }
  290. }
  291. }
  292. return doc, decodePatchKey(key)
  293. }
  294. func (d *partialDoc) set(key string, val *lazyNode) error {
  295. (*d)[key] = val
  296. return nil
  297. }
  298. func (d *partialDoc) add(key string, val *lazyNode) error {
  299. (*d)[key] = val
  300. return nil
  301. }
  302. func (d *partialDoc) get(key string) (*lazyNode, error) {
  303. return (*d)[key], nil
  304. }
  305. func (d *partialDoc) remove(key string) error {
  306. _, ok := (*d)[key]
  307. if !ok {
  308. return errors.Wrapf(ErrMissing, "Unable to remove nonexistent key: %s", key)
  309. }
  310. delete(*d, key)
  311. return nil
  312. }
  313. // set should only be used to implement the "replace" operation, so "key" must
  314. // be an already existing index in "d".
  315. func (d *partialArray) set(key string, val *lazyNode) error {
  316. idx, err := strconv.Atoi(key)
  317. if err != nil {
  318. return err
  319. }
  320. if idx < 0 {
  321. if !SupportNegativeIndices {
  322. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  323. }
  324. if idx < -len(*d) {
  325. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  326. }
  327. idx += len(*d)
  328. }
  329. (*d)[idx] = val
  330. return nil
  331. }
  332. func (d *partialArray) add(key string, val *lazyNode) error {
  333. if key == "-" {
  334. *d = append(*d, val)
  335. return nil
  336. }
  337. idx, err := strconv.Atoi(key)
  338. if err != nil {
  339. return errors.Wrapf(err, "value was not a proper array index: '%s'", key)
  340. }
  341. sz := len(*d) + 1
  342. ary := make([]*lazyNode, sz)
  343. cur := *d
  344. if idx >= len(ary) {
  345. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  346. }
  347. if idx < 0 {
  348. if !SupportNegativeIndices {
  349. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  350. }
  351. if idx < -len(ary) {
  352. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  353. }
  354. idx += len(ary)
  355. }
  356. copy(ary[0:idx], cur[0:idx])
  357. ary[idx] = val
  358. copy(ary[idx+1:], cur[idx:])
  359. *d = ary
  360. return nil
  361. }
  362. func (d *partialArray) get(key string) (*lazyNode, error) {
  363. idx, err := strconv.Atoi(key)
  364. if err != nil {
  365. return nil, err
  366. }
  367. if idx < 0 {
  368. if !SupportNegativeIndices {
  369. return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  370. }
  371. if idx < -len(*d) {
  372. return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  373. }
  374. idx += len(*d)
  375. }
  376. if idx >= len(*d) {
  377. return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  378. }
  379. return (*d)[idx], nil
  380. }
  381. func (d *partialArray) remove(key string) error {
  382. idx, err := strconv.Atoi(key)
  383. if err != nil {
  384. return err
  385. }
  386. cur := *d
  387. if idx >= len(cur) {
  388. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  389. }
  390. if idx < 0 {
  391. if !SupportNegativeIndices {
  392. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  393. }
  394. if idx < -len(cur) {
  395. return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
  396. }
  397. idx += len(cur)
  398. }
  399. ary := make([]*lazyNode, len(cur)-1)
  400. copy(ary[0:idx], cur[0:idx])
  401. copy(ary[idx:], cur[idx+1:])
  402. *d = ary
  403. return nil
  404. }
  405. func (p Patch) add(doc *container, op Operation) error {
  406. path, err := op.Path()
  407. if err != nil {
  408. return errors.Wrapf(ErrMissing, "add operation failed to decode path")
  409. }
  410. con, key := findObject(doc, path)
  411. if con == nil {
  412. return errors.Wrapf(ErrMissing, "add operation does not apply: doc is missing path: \"%s\"", path)
  413. }
  414. err = con.add(key, op.value())
  415. if err != nil {
  416. return errors.Wrapf(err, "error in add for path: '%s'", path)
  417. }
  418. return nil
  419. }
  420. func (p Patch) remove(doc *container, op Operation) error {
  421. path, err := op.Path()
  422. if err != nil {
  423. return errors.Wrapf(ErrMissing, "remove operation failed to decode path")
  424. }
  425. con, key := findObject(doc, path)
  426. if con == nil {
  427. return errors.Wrapf(ErrMissing, "remove operation does not apply: doc is missing path: \"%s\"", path)
  428. }
  429. err = con.remove(key)
  430. if err != nil {
  431. return errors.Wrapf(err, "error in remove for path: '%s'", path)
  432. }
  433. return nil
  434. }
  435. func (p Patch) replace(doc *container, op Operation) error {
  436. path, err := op.Path()
  437. if err != nil {
  438. return errors.Wrapf(err, "replace operation failed to decode path")
  439. }
  440. if path == "" {
  441. val := op.value()
  442. if val.which == eRaw {
  443. if !val.tryDoc() {
  444. if !val.tryAry() {
  445. return errors.Wrapf(err, "replace operation value must be object or array")
  446. }
  447. }
  448. }
  449. switch val.which {
  450. case eAry:
  451. *doc = &val.ary
  452. case eDoc:
  453. *doc = &val.doc
  454. case eRaw:
  455. return errors.Wrapf(err, "replace operation hit impossible case")
  456. }
  457. return nil
  458. }
  459. con, key := findObject(doc, path)
  460. if con == nil {
  461. return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing path: %s", path)
  462. }
  463. _, ok := con.get(key)
  464. if ok != nil {
  465. return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing key: %s", path)
  466. }
  467. err = con.set(key, op.value())
  468. if err != nil {
  469. return errors.Wrapf(err, "error in remove for path: '%s'", path)
  470. }
  471. return nil
  472. }
  473. func (p Patch) move(doc *container, op Operation) error {
  474. from, err := op.From()
  475. if err != nil {
  476. return errors.Wrapf(err, "move operation failed to decode from")
  477. }
  478. con, key := findObject(doc, from)
  479. if con == nil {
  480. return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing from path: %s", from)
  481. }
  482. val, err := con.get(key)
  483. if err != nil {
  484. return errors.Wrapf(err, "error in move for path: '%s'", key)
  485. }
  486. err = con.remove(key)
  487. if err != nil {
  488. return errors.Wrapf(err, "error in move for path: '%s'", key)
  489. }
  490. path, err := op.Path()
  491. if err != nil {
  492. return errors.Wrapf(err, "move operation failed to decode path")
  493. }
  494. con, key = findObject(doc, path)
  495. if con == nil {
  496. return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing destination path: %s", path)
  497. }
  498. err = con.add(key, val)
  499. if err != nil {
  500. return errors.Wrapf(err, "error in move for path: '%s'", path)
  501. }
  502. return nil
  503. }
  504. func (p Patch) test(doc *container, op Operation) error {
  505. path, err := op.Path()
  506. if err != nil {
  507. return errors.Wrapf(err, "test operation failed to decode path")
  508. }
  509. if path == "" {
  510. var self lazyNode
  511. switch sv := (*doc).(type) {
  512. case *partialDoc:
  513. self.doc = *sv
  514. self.which = eDoc
  515. case *partialArray:
  516. self.ary = *sv
  517. self.which = eAry
  518. }
  519. if self.equal(op.value()) {
  520. return nil
  521. }
  522. return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
  523. }
  524. con, key := findObject(doc, path)
  525. if con == nil {
  526. return errors.Wrapf(ErrMissing, "test operation does not apply: is missing path: %s", path)
  527. }
  528. val, err := con.get(key)
  529. if err != nil {
  530. return errors.Wrapf(err, "error in test for path: '%s'", path)
  531. }
  532. if val == nil {
  533. if op.value().raw == nil {
  534. return nil
  535. }
  536. return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
  537. } else if op.value() == nil {
  538. return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
  539. }
  540. if val.equal(op.value()) {
  541. return nil
  542. }
  543. return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
  544. }
  545. func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) error {
  546. from, err := op.From()
  547. if err != nil {
  548. return errors.Wrapf(err, "copy operation failed to decode from")
  549. }
  550. con, key := findObject(doc, from)
  551. if con == nil {
  552. return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: %s", from)
  553. }
  554. val, err := con.get(key)
  555. if err != nil {
  556. return errors.Wrapf(err, "error in copy for from: '%s'", from)
  557. }
  558. path, err := op.Path()
  559. if err != nil {
  560. return errors.Wrapf(ErrMissing, "copy operation failed to decode path")
  561. }
  562. con, key = findObject(doc, path)
  563. if con == nil {
  564. return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing destination path: %s", path)
  565. }
  566. valCopy, sz, err := deepCopy(val)
  567. if err != nil {
  568. return errors.Wrapf(err, "error while performing deep copy")
  569. }
  570. (*accumulatedCopySize) += int64(sz)
  571. if AccumulatedCopySizeLimit > 0 && *accumulatedCopySize > AccumulatedCopySizeLimit {
  572. return NewAccumulatedCopySizeError(AccumulatedCopySizeLimit, *accumulatedCopySize)
  573. }
  574. err = con.add(key, valCopy)
  575. if err != nil {
  576. return errors.Wrapf(err, "error while adding value during copy")
  577. }
  578. return nil
  579. }
  580. // Equal indicates if 2 JSON documents have the same structural equality.
  581. func Equal(a, b []byte) bool {
  582. ra := make(json.RawMessage, len(a))
  583. copy(ra, a)
  584. la := newLazyNode(&ra)
  585. rb := make(json.RawMessage, len(b))
  586. copy(rb, b)
  587. lb := newLazyNode(&rb)
  588. return la.equal(lb)
  589. }
  590. // DecodePatch decodes the passed JSON document as an RFC 6902 patch.
  591. func DecodePatch(buf []byte) (Patch, error) {
  592. var p Patch
  593. err := json.Unmarshal(buf, &p)
  594. if err != nil {
  595. return nil, err
  596. }
  597. return p, nil
  598. }
  599. // Apply mutates a JSON document according to the patch, and returns the new
  600. // document.
  601. func (p Patch) Apply(doc []byte) ([]byte, error) {
  602. return p.ApplyIndent(doc, "")
  603. }
  604. // ApplyIndent mutates a JSON document according to the patch, and returns the new
  605. // document indented.
  606. func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
  607. if len(doc) == 0 {
  608. return doc, nil
  609. }
  610. var pd container
  611. if doc[0] == '[' {
  612. pd = &partialArray{}
  613. } else {
  614. pd = &partialDoc{}
  615. }
  616. err := json.Unmarshal(doc, pd)
  617. if err != nil {
  618. return nil, err
  619. }
  620. err = nil
  621. var accumulatedCopySize int64
  622. for _, op := range p {
  623. switch op.Kind() {
  624. case "add":
  625. err = p.add(&pd, op)
  626. case "remove":
  627. err = p.remove(&pd, op)
  628. case "replace":
  629. err = p.replace(&pd, op)
  630. case "move":
  631. err = p.move(&pd, op)
  632. case "test":
  633. err = p.test(&pd, op)
  634. case "copy":
  635. err = p.copy(&pd, op, &accumulatedCopySize)
  636. default:
  637. err = fmt.Errorf("Unexpected kind: %s", op.Kind())
  638. }
  639. if err != nil {
  640. return nil, err
  641. }
  642. }
  643. if indent != "" {
  644. return json.MarshalIndent(pd, "", indent)
  645. }
  646. return json.Marshal(pd)
  647. }
  648. // From http://tools.ietf.org/html/rfc6901#section-4 :
  649. //
  650. // Evaluation of each reference token begins by decoding any escaped
  651. // character sequence. This is performed by first transforming any
  652. // occurrence of the sequence '~1' to '/', and then transforming any
  653. // occurrence of the sequence '~0' to '~'.
  654. var (
  655. rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
  656. )
  657. func decodePatchKey(k string) string {
  658. return rfc6901Decoder.Replace(k)
  659. }