Files
releases/test/cases/testdata/jsonpatch/coverage.yaml
T
Jasper Van der Jeugt 1e17cc0c62 Add json.patch builtin
This is an implementation of the `json.patch` builtin.  Previous discussions
about this include #2839 and #2167.

It does not use an external dependency but rather implements [RFC 6902] directly
on AST terms.  This avoids a conversion to JSON as well as the dependency; and
as an added bonus we can make `json.patch` work for sets as well, covering the
full space of AST terms.

In my first implementation I used a mutable approach by first creating a deep
copy and then modifying it in-place.  However, this leads to issues with
the cached `hash` values in objects on the path.  I replaced this with an
implementation that creates shallow copies.  The performance tradeoff is that
smaller patches should be faster; but replacing parts will be slower.  Since we
don't know about too many people using this, I think both sides are acceptable.

I vendored the [json-patch-tests] into the test suite in a way that should
make updating them fairly easy.  I am also testing the cases disabled there
(since they do work for us!) but I disabled two test cases by adding a new
`opa_disabled` key.  These are:

 -  Us allowing `"foo"` as path (which should be `"/foo"` if you interpret
    the RFC strictly).
 -  A duplicate entry in the JSON patch object which isn't caught by OPA
    since it's consistent.

I added some additional tests for sets and things seem to work.  I'm going
to try out this new functionality in our larger codebase to see if any issues
come up, but I expect it to hold up.  Update: we've been using this builtin
and haven't seen any issues so far.

[RFC 6902]: https://tools.ietf.org/html/rfc6902#section-4.4
[json-patch-tests]: https://github.com/json-patch/json-patch-tests

Signed-off-by: Jasper Van der Jeugt <jasper@fugue.co>
2020-11-24 14:54:58 -05:00

12 lines
278 B
YAML

cases:
# These tests cover mostly error scenarios.
- note: jsonpatch/set
query: data.main.result = x
want_result: []
modules:
- |
package main
doc = [1, 2, 3]
patch = [{"op": "add", "path": "1.2", "value": "foo"}]
result = r {r = json.patch(doc, patch)}