9 JSON R packages
R has 3 packages for working with JSON data
"RJSONIO"by Duncan Temple Lang"rjson"by Alex Couture-Beil"jsonlite"by Jeroen Ooms, Duncan Temple Lang, Jonathan Wallace
All packages provide 2 main functions, toJSON() and fromJSON(), that allow
conversion to and from data in JSON format, respectively.
We’ll focus on the functions from "jsonlite".
For illustration purposes, let us consider the package "jsonlite".
There are 2 primary functions in "jsonlite":
toJSON()converts an R object to a string in JSONfromJSON()converts JSON content to R objects
9.1 Function toJSON()
The function jsonlite::toJSON() converts an R object to a string in JSON.
Example: single number to JSON-array
Let’s begin with a super simple example by passing a single data value to the
function toJSON():
Example: vectors to JSON-arrays
Consider the following vectors
Applying toJSON() to the vectors num and lts produces JSON arrays:
The argument pretty = TRUE allows you to obtain a JSON string with added
indentation whitespace:
toJSON(num, pretty = TRUE)
#> [1, 2, 3, 4, 5]
toJSON(lts, pretty = TRUE)
#> ["a", "b", "c", "d", "e"]What about an R vector with named elements? For example, here’s a vector vec
Converting vec to JSON, we get:
As you can tell, the names of the elements in vec are lost in translation.
Example: matrix to JSON-array
Here’s another example from an matrix to a JSON array:
mat <- matrix(9:1, nrow = 3, ncol = 3)
mat
#> [,1] [,2] [,3]
#> [1,] 9 6 3
#> [2,] 8 5 2
#> [3,] 7 4 1toJSON() converts an R matrix into a JSON-array
Notice that the returned output arranges the values of the matrix row-by-row,
also referred to as row-major. This means that when the input is an R matrix,
toJSON() uses its argument matrix = "rowmajor".
You can change the arrangement to column-major by specifying the argument
matrix = "columnmajor":
Example: data frame to JSON-object
We can also use toJSON() on data frames. Here’s an example of an assembled
data frame swdf which will be converted to a JSON-object:
# toy data
sw_data <- rbind(
c("Anakin", "male", "Tatooine", "41.9BBY", "yes"),
c("Amidala", "female", "Naboo", "46BBY", "no"),
c("Luke", "male", "Tatooine", "19BBY", "yes"),
c("Leia", "female", "Alderaan", "19BBY", "no")
)
# convert to data.frame and add column names
swdf <- data.frame(sw_data, stringsAsFactors = FALSE)
names(swdf) <- c("Name", "Gender", "Homeworld", "Born", "Jedi")
swdf
#> Name Gender Homeworld Born Jedi
#> 1 Anakin male Tatooine 41.9BBY yes
#> 2 Amidala female Naboo 46BBY no
#> 3 Luke male Tatooine 19BBY yes
#> 4 Leia female Alderaan 19BBY noThe default output when you pass a data frame to jsonlite::toJSON() is
# convert R data.frame to JSON
sw_json = toJSON(swdf)
sw_json
#> [{"Name":"Anakin","Gender":"male","Homeworld":"Tatooine","Born":"41.9BBY","Jedi":"yes"},{"Name":"Amidala","Gender":"female","Homeworld":"Naboo","Born":"46BBY","Jedi":"no"},{"Name":"Luke","Gender":"male","Homeworld":"Tatooine","Born":"19BBY","Jedi":"yes"},{"Name":"Leia","Gender":"female","Homeworld":"Alderaan","Born":"19BBY","Jedi":"no"}]The argument dataframe gives you more control on the output. This argument
has three options:
"rows": each row is converted to a JSON-object with key-value pairs formed by"column_name": "row_value";
toJSON(swdf, dataframe = "rows")
#> [{"Name":"Anakin","Gender":"male","Homeworld":"Tatooine","Born":"41.9BBY","Jedi":"yes"},{"Name":"Amidala","Gender":"female","Homeworld":"Naboo","Born":"46BBY","Jedi":"no"},{"Name":"Luke","Gender":"male","Homeworld":"Tatooine","Born":"19BBY","Jedi":"yes"},{"Name":"Leia","Gender":"female","Homeworld":"Alderaan","Born":"19BBY","Jedi":"no"}]"columns": each column is converted into a JSON-object with a single key for each column, and values stored as arrays;
toJSON(swdf, dataframe = "columns")
#> {"Name":["Anakin","Amidala","Luke","Leia"],"Gender":["male","female","male","female"],"Homeworld":["Tatooine","Naboo","Tatooine","Alderaan"],"Born":["41.9BBY","46BBY","19BBY","19BBY"],"Jedi":["yes","no","yes","no"]}"values": the values in each column are converted to a JSON-array, and the names of the columns are lost.
9.2 Function fromJSON()
In practice, instead of converting R objects to JSON objects, it is more common to have data in JSON format which needs to be converted into an R object.
The function jsonlite::fromJSON() converts a JSON-object to an R object.
Example: JSON-object to R object
Consider a simple JSON-object, and its conversion to R with
jsonlite::fromJSON()
Notice that the obtained object is an R list in which the key becomes the name of the list, and the value becomes the content of the list’s element.
Consider a less simple JSON-object:
json_obj2 <- '{"name1": "Nicole", "name2": "Pleuni", "name3": "Rori"}'
fromJSON(json_obj2)
#> $name1
#> [1] "Nicole"
#>
#> $name2
#> [1] "Pleuni"
#>
#> $name3
#> [1] "Rori"Another example:
Example: JSON-object to R object
Suppose you have a JSON object with the following data:
{
"Name": ["Anakin","Amidala","Luke","Leia"],
"Gender": ["male","female","male","female"],
"Homeworld": ["Tatooine","Naboo","Tatooine","Alderaan"],
"Born": ["41.9BBY","46BBY","19BBY","19BBY"],
"Jedi": ["yes","no","yes","no"]
}
and assume that the above data is stored as a single (continuous) string in
an R character vector json_sw; applying fromJSON() to this string gives
you the following list:
fromJSON(json_sw)
#> $Name
#> [1] "Anakin" "Amidala" "Luke" "Leia"
#>
#> $Gender
#> [1] "male" "female" "male" "female"
#>
#> $Homeworld
#> [1] "Tatooine" "Naboo" "Tatooine" "Alderaan"
#>
#> $Born
#> [1] "41.9BBY" "46BBY" "19BBY" "19BBY"
#>
#> $Jedi
#> [1] "yes" "no" "yes" "no"Can this be transformed into a data frame? Yes, by passing the obtained list
to the function data.frame():
9.3 Reading JSON Data
Now that we have discussed the basics of JSON, and the common ways to convert
fromJSON() and toJSON(), let’s see how to read JSON data from the Web.
One of the typical ways to import JSON data from the Web to R is by passing
the url directly to fromJSON(). Another way is by passing the name of the
file with the JSON content as a single string to the function fromJSON().
Here’s an example reading a JSON string from the website Advice Slip. The url https://api.adviceslip.com/advice gives you a random advice (see figure below):
Figure 9.1: Random advice from Advice Slip
As you can tell, the content is a simple JSON string
#> $slip
#> $slip$id
#> [1] 9
#>
#> $slip$advice
#> [1] "True happiness always resides in the quest!"
Example: Colors in Hexadecimal Notation
The following data comes from one of Dave Eddy’s github repositories:
https://raw.githubusercontent.com/bahamas10/css-color-names/master/css-color-names.json
This is a JSON-object in which the keys are color-names, and the values are the hexadecimal digits of the corresponding color:
{
"aliceblue": "#f0f8ff",
"antiquewhite": "#faebd7",
"aqua": "#00ffff",
"aquamarine": "#7fffd4",
"azure": "#f0ffff",
...
"wheat": "#f5deb3",
"white": "#ffffff",
"whitesmoke": "#f5f5f5",
"yellow": "#ffff00",
"yellowgreen": "#9acd32"
}
We pass the url to jsonlite::fromJSON()
colors_json <- "https://raw.githubusercontent.com/bahamas10/css-color-names/master/css-color-names.json"
hex_colors <- fromJSON(colors_json)The output in hex_colors is a list with 148 elements;
the first five elements are displayed below: