Search code examples
rhttr

How to efficiently send a dataframe with multiple rows via httr::PUT


Probably due to my limited knowledge of communicating with APIs, (Which I am trying to remedy :) ) I seem to be unable to execute a put request for more than 1 row of a dataframe at a time. for example, if df_final consists of 1 row, the following code works. If there are multiple rows, it fails and I get a 400 status.

reqBody <- list(provName = df_final$Provider,site = df_final$Site,
                monthJuly = df_final$July, monthAugust = df_final$August,
                monthSeptember = df_final$September, monthOctober =df_final$October,
monthNovember = df_final$November ,
                monthDecember = df_final$December, monthJanuary = df_final$January, monthFebruary =     df_final$February,
                monthMarch = df_final$March, monthApril = df_final$April, monthMay = df_final$May,
                monthJune = df_final$June,
                assumptions = paste("Monthly Volume:", input$Average, "; Baseline Seasonality:",     input$Year, "; Trend:", input$Year_slopes),
                rationale = as.character(input$Comments), fiscalYear = FY_SET, updateDtm = Sys.time())

r <- PUT(fullURL, body = reqBody, encode = "json", content_type_json())

Using with_verbose() I am able to see that the json being sent is formatted differently for the 2 cases. I haven't found anything in the documentation ( https://cran.r-project.org/web/packages/httr/httr.pdf) that has been particularly helpful in overcoming this.

The format it appears to be sending out in the first instance (1 row in the data frame) Looks like this:

{"provName":"Name","site":"site","monthJuly":56,"monthAugust":71,"monthSeptember":65,"monthOctober":78,"monthNovember":75,"monthDecember":98,"monthJanuary":23,"monthFebruary":39,"monthMarch":38,"monthApril":42,"monthMay":57,"monthJune":54,"assumptions":"Monthly Volume: Last 3 Months of 2019 ; Baseline Seasonality: 2017 ; Trend: 2017","rationale":"","fiscalYear":2022,"updateDtm":"2023-02-03 15:19:40"} and again, it works sans issues.

With 2 rows I get the following format: {"provName":["Name","Name"],"site":["site","site"],"monthJuly":[56,56],"monthAugust": [71,71],"monthSeptember":[65,65],"monthOctober":[78,78],"monthNovember":[75,75],"monthDecember": [98,98],"monthJanuary":[23,23],"monthFebruary":[39,39],"monthMarch":[38,38],"monthApril": [42,42],"monthMay":[57,57],"monthJune":[54,54],"assumptions":["Monthly Volume: Last 3 Months of 2019 ; Baseline Seasonality: 2017 ; Trend: 2017","Monthly Volume: Last 3 Months of 2019 ; Baseline Seasonality: 2017 ; Trend: 2017"],"rationale":["",""],"17":2,"18":2}

And it fails with status 400.

I suppose I could use lapply and PUT for each row, however with thousands of rows in a dataframe, I think that would be less than ideal.

Anyone have any light to share on this?

Any help would be greatly appreciated!

PS: this didn't really answer my question R httr put requets

and as I mentioned, Doing something like this is not ideal: Convert each data frame row to httr body parameter list without enumeration


Solution

  • Looks like you are using a list as the request body. Use a data frame instead.

    Lists and data frames get serialized to JSON differently:

    jsonlite::toJSON(list(x = 1:2, y = 3:4))
    #> {"x":[1,2],"y":[3,4]}
    
    jsonlite::toJSON(data.frame(x = 1:2, y = 3:4))
    #> [{"x":1,"y":3},{"x":2,"y":4}]