Reading JSON into R usually leaves you with some deeply-nested list objects which are a pain to munge and navigate — applying path expressions is one way to make this easier. rjsonpath implements JSONPath, a selector / querying language for JSON, similar to XPath for XML.
As an example, take this simple JSON:
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}Via read_json this can be read into R as:
json
#> $menu
#> $menu$id
#> [1] "file"
#>
#> $menu$value
#> [1] "File"
#>
#> $menu$popup
#> $menu$popup$menuitem
#> $menu$popup$menuitem[[1]]
#> value onclick
#> "New" "CreateNewDoc()"
#>
#> $menu$popup$menuitem[[2]]
#> value onclick
#> "Open" "OpenDoc()"
#>
#> $menu$popup$menuitem[[3]]
#> value onclick
#> "Close" "CloseDoc()"Pretty horrible right? To gather all the onclick methods into a vector with base R you might write:
sapply(json$menu$popup$menuitem, `[[`, "onclick")
#> [1] "CreateNewDoc()" "OpenDoc()" "CloseDoc()"Using rjsonpath this could instead be:
json_path(json, "$.menu.popup.menuitem[*].onclick")
#> [1] "CreateNewDoc()" "OpenDoc()" "CloseDoc()"Or even just:
json_path(json, "$..onclick")
#> NULLFor more more complex examples, see below.
For more complex JSON documents it’s common to combine filters, array slices and recursive descent. The following examples use a simple “store” object similar to the one in the original JSONPath specification:
Select only books cheaper than 10:
json_path(store, "$.store.book[?(@.price < 10)].title")
#> NULLSelect books that have an isbn field:
json_path(store, "$.store.book[?(@.isbn)].title")
#> [1] "Moby Dick" "The Lord of the Rings"Get all prices anywhere under store:
json_path(store, "$.store..price")
#> [1] 8.95 12.99 8.99 22.99 19.95Get all authors anywhere in the document:
json_path(store, "$..author")
#> [1] "Nigel Rees" "Evelyn Waugh" "Herman Melville" "J. R. R. Tolkien"Select a slice of books (second and third) and return their titles:
json_path(store, "$.store.book[1:3].title")
#> [1] "Sword of Honour" "Moby Dick"Select a non‑contiguous subset of books by index:
json_path(store, "$.store.book[0,3].title")
#> [1] "Sayings of the Century" "The Lord of the Rings"