LRD
LRD

Reputation: 361

list and dataframe combined into a json

I need to obtain a JSON like this example from R:

{
  "content": [
       {
           "id": "id_1",
           "classes": {
               "animal": "cat",
               "place": "house",
               "score": 75
           }
       },
       {
           "id": "id_2",
           "classes": {
               "animal": "dog",
               "place": "house",
               "score": 81
           }
       },
       {
           "id": "id_3",
           "classes": {
               "animal": "duck",
               "place": "garden",
               "score": 63
          }
       }
    ],
    "book":{
        "pageNumber": 1,
        "animalsCount": 23,
        "reference": "BH"
     }
}

I'm doing the following in R:

library(jsonlite)

df <- data.frame(id = c("id_1", "id_2", "id_3"), animal = c("cat", "dog", "duck"), 
            place = c("house", "house", "house"), score=c(75, 81, 63))

pagenum <- 1
ref <- "BH"


getJSON <- function(dfinfo, pag, ref_name){

   classes <- data.frame(animal = dfinfo$animal)
   classes$place <- dfinfo$place
   classes$score <- dfinfo$score

   df1 <- data.frame(id = dfinfo$id)
   df1$classes <- classes

   df2 <- data.frame(pageNumber = pagenum)
   df2$animalsCount <- nrow(df)
   df2$reference <- ref

   info_to_json <- list(content = classes, book = df2)
   info_to_json <- toJSON(info_to_json, pretty=TRUE)

   return(info_to_json)
}


getJSON(df, pagenum, ref)

But, while the "content" part shows up correctly (as a list), the "book" part appears like a list:

 "book":[
    {
        "pageNumber": 1,
        "animalsCount": 23,
        "reference": "BH"
    }
  ]

which I understand because info_to_json is a list, but I need it to be without [ ] as shown above, but I don't know how to achieve it, how to combine both dataframes to get a list-dataframe in the JSON.

I've tried, instead of converting the list info_to_json to a JSON using the toJSON() function, adding the following line on top of my function getJSON():

 #'@serializer unboxed JSON

But this unboxes "book" if book is just a parameter (like "book"=3) but not if it's a dataframe as I have.

How can I achieve that?

And also, is there any better way to convert the dataframes into the JSON without having to specify every parameter manually? or this is the only way with R?

Upvotes: 2

Views: 38

Answers (2)

amatsuo_net
amatsuo_net

Reputation: 2448

There are several issues:

  1. you create a data.frame for book, but what you need is a flat list
  2. the content part should be converted into a nested structure.

My solution to take care of both is:


library(tidyverse)

getJSON <- function(dfinfo, pag, ref_name){
    nested_df <- dfinfo %>% rowwise() %>%
        do(id = .$id,
           classes = .[2:4])
    data_book <- list(pageNumber = pagenum, animalsCount = nrow(df), 
                      reference = ref)

    info_to_json <- list(content = nested_df, book = data_book)
    info_to_json <- toJSON(info_to_json, pretty=TRUE, auto_unbox = TRUE)

    return(info_to_json)
}

getJSON(df, pagenum, ref)


In the rowwise() section of the function, each row of df_info is converted to a nested df.

Upvotes: 1

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84529

Use a list instead of a dataframe, and set the option auto_unbox = TRUE :

  df2 <- list(
    pageNumber = pagenum,
    animalsCount = nrow(df),
    reference = ref_name
  )

  info_to_json <- list(content = classes, book = df2)
  info_to_json <- toJSON(info_to_json, pretty=TRUE, auto_unbox = TRUE)

Upvotes: 1

Related Questions