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::toJSON
whendata
,patch
,data_x
, and / ordata_y
is an R object. It is appropriate to add thejsonlite::toJSON()
argumentauto_unbox = TRUE
whenpatch
is 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"}
#> ]