For an NA value in a lists column in a data frame, toJSON outputs an empty list (instead of nothing)
When using toJSON() on a data frame, default behavior for NA values is that no field is included in the JSON record (see also section 2.4.3 in The jsonlite Package: A Practical and Consistent Mapping Between JSON Data and R Objects). I like this! However, this doesn't appear to work for list columns:
test = structure(list(
foo = c(NA, TRUE, FALSE),
bar = c("Aladdin", NA, "Mario"),
nested_list = c(list(list(c("cat", "dog"), c("tree"))),
list(list(c("cat", "dog"), c("tree"))),
NA)),
row.names = c(NA, -3L), class = "data.frame")
test
# foo bar nested_list
# 1 NA Aladdin cat, dog, tree
# 2 TRUE <NA> cat, dog, tree
# 3 FALSE Mario NA
is.na(test)
# foo bar nested_list
# [1,] TRUE FALSE FALSE
# [2,] FALSE TRUE FALSE
# [3,] FALSE FALSE TRUE
jsonlite::toJSON(test, pretty = TRUE)
# [
# {
# "bar": "Aladdin",
# "nested_list": [
# ["cat", "dog"],
# ["tree"]
# ]
# },
# {
# "foo": true,
# "nested_list": [
# ["cat", "dog"],
# ["tree"]
# ]
# },
# {
# "foo": false,
# "bar": "Mario",
# "nested_list": [null] # NOTE: nested_list = NA in data frame above
# }
# ]
On a related note, I would propose a small change to the "na" argument. From ?jsonlite::toJSON:
| na | how to print NA values: must be one of 'null' or 'string'. Defaults are class specific |
|---|
I think that it would be helpful for "na" to also have the possible value "skip", which would result in no field in the JSON record for NA values.
It would be helpful if a similar logic could be implemented for NULLs. In the following example, the empty _children-entry causes an error for toastui::datagrid().
json_raw <- paste0('
[
{
"id": 549731,
"name": "Beautiful Lies",
"artist": "Birdy",
"listenCount": 5000,
"_children": [
{
"id": 491379,
"name": "Chaos And The Calm",
"artist": "James Bay",
"listenCount": 5000
}
]
},
{
"id": 436461,
"name": "X",
"artist": "Ed Sheeran",
"listenCount": 5000
}
]')
jsonlite::toJSON(jsonlite::fromJSON(json_raw), pretty = TRUE)
#> [
#> {
#> "id": 549731,
#> "name": "Beautiful Lies",
#> "artist": "Birdy",
#> "listenCount": 5000,
#> "_children": [
#> {
#> "id": 491379,
#> "name": "Chaos And The Calm",
#> "artist": "James Bay",
#> "listenCount": 5000
#> }
#> ]
#> },
#> {
#> "id": 436461,
#> "name": "X",
#> "artist": "Ed Sheeran",
#> "listenCount": 5000,
#> "_children": {}
#> }
#> ]
Just saw that this was also requested in #143