j_patch_apply() uses JSON Patch
https://jsonpatch.com to transform JSON 'data' according the
rules in JSON 'patch'.
j_patch_from() computes a JSON patch describing the
difference between two JSON documents.
j_patch_op() translates R arguments to the JSON
representation of a patch, validating and 'unboxing' arguments
as necessary.
Usage
j_patch_apply(data, patch, as = "string", ...)
j_patch_from(data_x, data_y, as = "string", ...)
j_patch_op(op, path, ...)
# Default S3 method
j_patch_op(op, path, ..., from = NULL, value = NULL)
# S3 method for class 'j_patch_op'
j_patch_op(op, ...)
# S3 method for class 'j_patch_op'
c(..., recursive = FALSE)
# S3 method for class 'j_patch_op'
print(x, ...)Arguments
- data
JSON character vector, file, URL, or an R object to be converted to JSON using
jsonline::fromJSON(data, ...).- patch
JSON 'patch' as character vector, file, URL, R object, or the result of
j_patch_op().- as
character(1) return type;
"string"returns a JSON string,"R"returns an R object using the rules inas_r().- ...
For
j_patch_apply()andj_patch_diff(), arguments passed tojsonlite::toJSONwhendata,patch,data_x, and / ordata_yis an R object. It is appropriate to add thejsonlite::toJSON()argumentauto_unbox = TRUEwhenpatchis an R object and any 'value' fields are JSON scalars; for more complicated scenarios 'value' fields should be marked withjsonlite::unbox()before being passed toj_patch_*().For
j_patch_op()the...are additional arguments to the patch operation, e.g.,path = ',value = '.- data_x
As for
data.- data_y
As for
data.- op
A patch operation (
"add","remove","replace","copy","move","test"), or when 'piping' an object created byj_patch_op().- path
A character(1) JSONPointer path to the location being patched.
- from
A character(1) JSONPointer path to the location an object will be copied or moved from.
- value
An R object to be translated into JSON and used during add, replace, or test.
- recursive
Ignored.
- x
An object produced by
j_patch_op().
Value
j_patch_apply() returns a JSON string or R object
representing 'data' patched according to 'patch'.
j_patch_from() returns a JSON string or R object
representing the difference between 'data_x' and 'data_y'.
j_patch_op() returns a character vector subclass that can
be used in j_patch_apply().
Details
For j_patch_apply(), 'patch' is a JSON array of objects. Each
object describes how the patch is to be applied. Simple examples
are available at https://jsonpatch.com, with verbs 'add',
'remove', 'replace', 'copy' and 'test'. The 'path' element of each
operation is a JSON pointer; remember that JSON arrays are 0-based.
add– add elements to an existing document.{"op": "add", "path": "/biscuits/1", "value": {"name": "Ginger Nut"}}remove– remove elements from a document.{"op": "remove", "path": "/biscuits/0"}replace– replace one element with another{ "op": "replace", "path": "/biscuits/0/name", "value": "Chocolate Digestive" }copy– copy a path to another location.{"op": "copy", "path": "/best_biscuit", "from": "/biscuits/0"}move– move a path to another location.{"op": "move", "path": "/cookies", "from": "/biscuits"}test– test for the existence of a path; if the path does not exist, do not apply any of the patch.{"op": "test", "path": "/best_biscuit/name", "value": "Choco Leibniz"}
The examples below illustrate a patch with one (a JSON array with a
single object) or several (a JSON array with several arguments)
operations. j_patch_apply() fits naturally into a pipeline
composed with |> to transform JSON between representations.
The j_patch_op() function takes care to ensure that op, path,
and from arguments are 'unboxed' (represented as JSON scalars
rather than arrays). The user must ensure that value is
represented correctly by applying jsonlite::unbox() to individual
elements or adding auto_unbox = TRUE to .... Examples
illustrate these different scenarios.
Examples
data_file <-
system.file(package = "rjsoncons", "extdata", "patch_data.json")
## add a biscuit
patch <- '[
{"op": "add", "path": "/biscuits/1", "value": {"name": "Ginger Nut"}}
]'
j_patch_apply(data_file, patch, as = "R") |> str()
#> List of 1
#> $ biscuits:List of 3
#> ..$ :List of 1
#> .. ..$ name: chr "Digestive"
#> ..$ :List of 1
#> .. ..$ name: chr "Ginger Nut"
#> ..$ :List of 1
#> .. ..$ name: chr "Choco Leibniz"
## add a biscuit and choose a favorite
patch <- '[
{"op": "add", "path": "/biscuits/1", "value": {"name": "Ginger Nut"}},
{"op": "copy", "path": "/best_biscuit", "from": "/biscuits/2"}
]'
biscuits <- j_patch_apply(data_file, patch)
as_r(biscuits) |> str()
#> List of 2
#> $ biscuits :List of 3
#> ..$ :List of 1
#> .. ..$ name: chr "Digestive"
#> ..$ :List of 1
#> .. ..$ name: chr "Ginger Nut"
#> ..$ :List of 1
#> .. ..$ name: chr "Choco Leibniz"
#> $ best_biscuit:List of 1
#> ..$ name: chr "Choco Leibniz"
j_patch_from(biscuits, data_file, as = "R") |> str()
#> List of 3
#> $ :List of 3
#> ..$ op : chr "replace"
#> ..$ path : chr "/biscuits/1/name"
#> ..$ value: chr "Choco Leibniz"
#> $ :List of 2
#> ..$ op : chr "remove"
#> ..$ path: chr "/biscuits/2"
#> $ :List of 2
#> ..$ op : chr "remove"
#> ..$ path: chr "/best_biscuit"
if (requireNamespace("jsonlite", quietly = TRUE)) {
## helper for constructing patch operations from R objects
j_patch_op(
"add", path = "/biscuits/1", value = list(name = "Ginger Nut"),
## 'Ginger Nut' is a JSON scalar, so auto-unbox the 'value' argument
auto_unbox = TRUE
)
j_patch_op("remove", "/biscuits/0")
j_patch_op(
"replace", "/biscuits/0/name",
## also possible to unbox arguments explicitly
value = jsonlite::unbox("Chocolate Digestive")
)
j_patch_op("copy", "/best_biscuit", from = "/biscuits/0")
j_patch_op("move", "/cookies", from = "/biscuits")
j_patch_op(
"test", "/best_biscuit/name", value = "Choco Leibniz",
auto_unbox = TRUE
)
## several operations
value <- list(name = jsonlite::unbox("Ginger Nut"))
ops <- c(
j_patch_op("add", "/biscuits/1", value = value),
j_patch_op("copy", path = "/best_biscuit", from = "/biscuits/0")
)
ops
ops <-
j_patch_op("add", "/biscuits/1", value = value) |>
j_patch_op("copy", path = "/best_biscuit", from = "/biscuits/0")
ops
}
#> [
#> {"op": "add", "path": "/biscuits/1", "value": {"name": "Ginger Nut"}},
#> {"op": "copy", "path": "/best_biscuit", "from": "/biscuits/0"}
#> ]