2

when using jsonlite to import a json that has an array inside other array I get an undesired unnamed list. Exemple below:

myjson=jsonlite::fromJSON('{
  "class" : "human",
  "type" : [{ 
  "shape":"thin",
  "face":[{"eyes":"blues","hair":"brown"}]
}]
}')

str(myjson)

List of 2
 $ class: chr "human"
 $ type :'data.frame':  1 obs. of  2 variables:
  ..$ shape: chr "thin"
  ..$ face :List of 1
  .. ..$ :'data.frame': 1 obs. of  2 variables:
  .. .. ..$ eyes: chr "blues"
  .. .. ..$ hair: chr "brown"

I would like to access the "eyes" field as below (however it doesn't work):

myjson[["type"]][["face"]][["eyes"]]
NULL

Instead, I need to add "[[1]]" in order to make it works:

myjson[["type"]][["face"]][[1]][["eyes"]]
[1] "blues"

Any ideas how could I format the json to get rid of this unnamed list?

Fallen lord
  • 196
  • 1
  • 12

1 Answers1

1

The thing is, unnamed lists are used whenever there is a JSON vector [{}, {}, ...]. The fact that your first vector is turned into a named list and the second, inner one, is turned into an unnamed list is because jsonlite::fromJSON has arguments simplifyDataFrame = TRUE and flatten = TRUE by default, which have this behavior. I haven't looked into the source code, but it seems that the simplification involved (transforming a vector with only one element into a named list) only simplify the top-level objects.

A work around is to apply a function that turns any unnamed list with only a single object into the object itself.

my_json <- lapply(my_json, function(x) {
    if (is.list(x)) # if element is a list, replace it with its first element
        return(lapply(x, function(y) {
            return(y[[1]])
        }))
    else
        return(x)
})
eduardokapp
  • 1,612
  • 1
  • 6
  • 28