mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-16 21:31:34 -06:00
1e17cc0c62
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>
12 lines
278 B
YAML
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)}
|