Reputation: 185
I can call the api from local Rstudio by this script successfully:
The api is published in Domino datalab
library(httr)
library(rjson)
url <- "XXX"
response <- POST(
url,
authenticate("XXX", "XXX", type = "basic"),
body=toJSON(list(data=list(
"product_list_Zone"= "ZONE 1",
"product_list_brand"= "A1",
"product_list_FY22SRP"=390,
"commodityPrice"= 415.59))),
content_type("application/json"))
However, I want to have multiple values for each of "product_list_brand" and "product_list_FY22SRP". Say, "product_list_brand" can be A1 and A2, and "product_list_FY22SRP" will be 390 (corresponding to A1) and 400 (corresponding to A2).
I tried something like replacing "product_list_brand"= "A1"
with "product_list_brand"= c("A1, A2")
but this won't work. I also tried "product_list_brand"= toJSON(c("A1, A2"))
but it won't work still.
So how should I have a correct output with multiple values for each of "product_list_brand" and "product_list_FY22SRP" inputs? I think it's a format issue and I can call my api successfully function using "product_list_brand"= c("A1, A2")
(but not calling the api, it did not work).
(and one interesting thing is I have to use the format body=toJSON(list(data=list()))
here, as per the example from Domino datalab, so far using other formats will occur errors. )
Thanks in advance!
Upvotes: 0
Views: 288
Reputation: 160607
Whether or not you can pass multiple values in on argument is controlled wholly on the API side, it has nothing to do with the client. If the remote end does not support it, the only thing you can do is repeat the query with individual values.
Perhaps:
func <- function(url, bodies, ..., expand = FALSE) {
bodies <- if (expand) do.call(expand.grid, bodies) else as.data.frame(bodies)
bodies <- do.call(mapply, c(list(FUN = function(...) jsonlite::toJSON(list(data = list(...)))), bodies))
lapply(bodies, function(body) do.call(httr::POST, c(list(url = url, body = body), ...)))
}
func("XXX",
bodies = list("product_list_Zone" = "ZONE 1", "product_list_brand" = c("A1", "A2"),
"product_list_FY22SRP" = 390, "commodityPrice" = 415.59),
httr::authenticate("XXX", "XXX", type = "basic"),
httr::content_type("application/json"))
This should always return a list
, each element is the result from one call to the API.
The only difference that expand=
makes is if/when you provide more than one multi-value argument. For an example, I'll use two zones and two brands, and interrupt the steps to show the body
passed to each call to func
:
cat(sep = "\n",
func("XXX", bodies = list("product_list_Zone" = c("ZONE 1", "ZONE 2"), "product_list_brand" = c("A1","A2"), "product_list_FY22SRP" = 390, "commodityPrice" = 415.59), httr::authenticate("XXX", "XXX", type = "basic"), httr::content_type("application/json"))
)
# {"data":{"product_list_Zone":["ZONE 1"],"product_list_brand":["A1"],"product_list_FY22SRP":[390],"commodityPrice":[415.59]}}
# {"data":{"product_list_Zone":["ZONE 2"],"product_list_brand":["A2"],"product_list_FY22SRP":[390],"commodityPrice":[415.59]}}
cat(sep = "\n",
func("XXX", bodies = list("product_list_Zone" = c("ZONE 1", "ZONE 2"), "product_list_brand" = c("A1","A2"), "product_list_FY22SRP" = 390, "commodityPrice" = 415.59), httr::authenticate("XXX", "XXX", type = "basic"), httr::content_type("application/json"), expand = TRUE)
)
# {"data":{"product_list_Zone":["ZONE 1"],"product_list_brand":["A1"],"product_list_FY22SRP":[390],"commodityPrice":[415.59]}}
# {"data":{"product_list_Zone":["ZONE 2"],"product_list_brand":["A1"],"product_list_FY22SRP":[390],"commodityPrice":[415.59]}}
# {"data":{"product_list_Zone":["ZONE 1"],"product_list_brand":["A2"],"product_list_FY22SRP":[390],"commodityPrice":[415.59]}}
# {"data":{"product_list_Zone":["ZONE 2"],"product_list_brand":["A2"],"product_list_FY22SRP":[390],"commodityPrice":[415.59]}}
With expand=FALSE
(the default), it is assumed that the arguments will "recycle" (in R's sense) naturally: all vectors are either:
n
, the longest argumentn
(side point: this is the feature of R's recycling that I do not think is a sane default ...)For example, data.frame(a=1, b=1:2, d=1:6)
will not err, and shows all three of the rules above.
With expand=TRUE
, though, it uses expand.grid
to find all permutations of all arguments.
Caveat emptor: I did not test this with an actual API, so the POST
functionality might need some tweaking.
Upvotes: 1