Tsaari
Tsaari

Reputation: 103

R: jsonlite - export key:value pairs from a list of lists

I have a list of lists which are of variable length. The first value of each nested list is the key, and the rest of the values in the list will be the array entry. It looks something like this:

[[1]]
[1] "Bob"      "Apple"

[[2]]
[1] "Cindy"    "Apple"     "Banana"      "Orange"   "Pear"   "Raspberry"         

[[3]]
[1] "Mary"     "Orange"    "Strawberry"

[[4]]
[1] "George"   "Banana"

I've extracted the keys and entries as follows:

keys <- lapply(x, '[', 1)
entries <- lapply(x, '[', -1)

but now that I have these, I don't know how I can associate a key:value pair in R without creating a matrix first, but this is silly since my data don't fit in a rectangle anyway (every example I've seen uses the column names from a matrix as the key values).

This is my crappy method using a matrix, assigning rownames, and then using jsonLite to export to JSON.

#Create a matrix from entries, without recycling
#I found this function on StackOverflow which seems to work...
cbind.fill <- function(...){
  nm <- list(...) 
  nm <- lapply(nm, as.matrix)
  n <- max(sapply(nm, nrow)) 
  do.call(cbind, lapply(nm, function (x) 
    rbind(x, matrix(, n-nrow(x), ncol(x))))) 
}
#Call said function
matrix <- cbind.fill(entries)
#Transpose the thing
matrix <- t(matrix)
#Set column names
colnames(matrix) <- keys
#Export to json
json<-toJSON(matrix)

The result is good, but the implementation sucks. Result:

[{"Bob":["Apple"],"Cindy":["Apple","Banana","Orange","Pear","Raspberry"],"Mary":["Orange","Strawberry"],"George":["Banana"]}]

Please let me know of better ways that might exist to accomplish this.

Upvotes: 1

Views: 1080

Answers (3)

timelyportfolio
timelyportfolio

Reputation: 6579

I think this has already been sufficiently answered but here is a method using purrr and jsonlite.

library(purrr)
library(jsonlite)


sample_data <- list(
  list("Bob","Apple"),
  list("Cindy","Apple","Banana","Orange","Pear","Raspberry"),
  list("Mary","Orange","Strawberry"),
  list("George","Banana")
)

sample_data %>%
  map(~set_names(list(.x[-1]),.x[1])) %>%
  toJSON(auto_unbox=TRUE, pretty=TRUE)

Upvotes: 0

Jthorpe
Jthorpe

Reputation: 10194

How about:

names(entries) <- unlist(keys) 
toJSON(entries)

Upvotes: 1

Parfait
Parfait

Reputation: 107687

Consider the following lapply() approach:

library(jsonlite)
entries <- list(c('Bob', 'Apple'),
                c('Cindy', 'Apple', 'Banana', 'Orange','Pear','Raspberry'),
                c('Mary', 'Orange', 'Strawberry'),
                c('George', 'Banana'))

# ITERATE ALL CONTENTS EXCEPT FIRST
inner <- list()
nestlist <- lapply(entries, 
                          function(i) {
                          inner <- i[2:length(i)]
                          return(inner)
                   })

# NAME EACH ELEMENT WITH FIRST ELEMENT
names(nestlist) <- lapply(entries, function(i) i[1])
#$Bob
#[1] "Apple"    
#$Cindy
#[1] "Apple"     "Banana"    "Orange"    "Pear"      "Raspberry"    
#$Mary
#[1] "Orange"     "Strawberry"    
#$George
#[1] "Banana"

x <- toJSON(list(nestlist), pretty=TRUE)
x
#[
#  {
#    "Bob": ["Apple"],
#    "Cindy": ["Apple", "Banana", "Orange", "Pear", "Raspberry"],
#    "Mary": ["Orange", "Strawberry"],
#    "George": ["Banana"]
#  }
#] 

Upvotes: 1

Related Questions