TestingInProd
TestingInProd

Reputation: 379

Create Json object with multiple children in R

How to create a JSON object with data.frame(MyData) something like below.I tried other methods but this problem looks unique.

ID   Station   Size 
1      Zeta    Big  
2      Zeta Medium  
3      Zeta  small  
4      Yota    Big  
5      Yota Medium  
6      Yota  small  

Expected result

{
    "name": "bubble",
    "children": [{
        "name": "Zeta",
        "children": [{
            "name": "big"
        }, {
            "name": "Medium"
        }, {
            "name": "small"
        }]
    }, {
        "name": "Yota",
        "children": [{
            "name": "big"
        }, {
            "name": "Medium"
        }, {
            "name": "small"
        }]
    }]
}

Here is what I searched and was not able to alter

makeList<-function(x){
  if(ncol(x)>2){
    listSplit<-split(x[-1],x[1],drop=T)
    lapply(names(listSplit),function(y){list(name=y,children=makeList(listSplit[[y]]))})
  }else{
    lapply(seq(nrow(x[1])),function(y){list(name=x[,-1][y])})
  }
}


jsonOut<-toJSON(list(name="MyData",children=makeList(MyData[1])))
cat(jsonOut)

Upvotes: 3

Views: 1961

Answers (1)

tospig
tospig

Reputation: 8333

Data

The data I'm using is

df <- data.frame(Station = c(rep("Zeta", 3), rep("Yota", 3)),
                 Size = rep(c("Big","Medium","Small"),2), stringsAsFactors = F)

Method

Working backwards we can see the structure we're after

t <- "{\"name\": \"bubble\",\"children\": [{\"name\": \"Zeta\",\"children\": [{\"name\": \"big\"}, {\"name\": \"Medium\" }, {\"name\": \"small\"}]}, {\"name\": \"Yota\",\"children\": [{\"name\": \"big\"}, {\"name\": \"Medium\"}, {\"name\": \"small\"}]}]}\""

library(jsonlite)
l <- fromJSON(t)
str(l)
 #List of 2
 #$ name    : chr "bubble"
 #$ children:'data.frame':  2 obs. of  2 variables:
 #  ..$ name    : chr [1:2] "Zeta" "Yota"
 # ..$ children:List of 2
 # .. ..$ :'data.frame':    3 obs. of  1 variable:
 #  .. .. ..$ name: chr [1:3] "big" "Medium" "small"  
 # .. ..$ :'data.frame':    3 obs. of  1 variable:
 #  .. .. ..$ name: chr [1:3] "big" "Medium" "small"

To reconstruct this we need

## first element
lst <- list(name = "bubble")

## second element
l_child1 <- l$children$children[[1]]
l_child2 <- l$children$children[[2]]
l_child <- list(data.frame(name=l_child1), data.frame(name=l_child2))

n <- c("Zeta", "Yota")
df_child <- data.frame(name = n, stringsAsFactors = F)

df_child$children <- l_child

lst <- list(name = "bubble", children = df_child)

toJSON(lst, pretty=F)
# {"name":["bubble"],"children":[{"name":"Zeta","children":[{"name":"big"},{"name":"Medium"},{"name":"small"}]},{"name":"Yota","children":[{"name":"big"},{"name":"Medium"},{"name":"small"}]}]} 

So we know we need the structures of l_child1, l_child2, l_child, df_child, but how do we get there from our original df, and for the general case?

Solution

df$Size gives us our l_child lists, and there is a size for each Station. So we can use lapply to give us our lists of children, for each 'group' of Station.

n <- unique(df$Station)
l_child <- lapply(1:length(n), FUN=function(x){
  t <- data.frame(name = (df[df$Station == n[x], "Size"]), stringsAsFactors=F)
  return(t)
})

And we can now construct our final list

df_child <- data.frame(name = n, stringsAsFactors = FALSE)
df_child$children <- l_child

lst <- list(name = "bubble", children = df_child)

And to check:

> toJSON(lst, pretty=T)
{
  "name": ["bubble"],
  "children": [
    {
      "name": "Zeta",
      "children": [
        {
          "name": "Big"
        },
        {
          "name": "Medium"
        },
        {
         "name": "Small"
        } 
      ]
    },
     ... etc...

Upvotes: 2

Related Questions