使用 R 的水管工 - 创建 GET 端点来托管 CSV 格式的数据,而不是 JSON



我认为这是 R 水管工库的一个很好的快速演示,但主要是我正在努力以 csv 格式提供数据

我正在使用 R 的水管工包来托管我的一些体育数据的 API 端点。目前,我有一些数据可以获取我试图服务的 MLB 棒球队的胜利总数。使用水管工,我设置了以下 2 个脚本:

setupAPI.R:使用两个 GET 端点设置我的 API:

library(plumber)
library(jsonlite)
# load in some test sports data to host
mydata = structure(list(Team = structure(c(8L, 20L, 7L, 28L, 2L, 30L, 
23L, 1L, 6L, 19L), .Label = c("Angels", "Astros", "Athletics", 
"Blue Jays", "Braves", "Brewers", "Cardinals", "Cubs", "Diamondbacks", 
"Dodgers", "Giants", "Indians", "Mariners", "Marlins", "Mets", 
"Nationals", "Orioles", "Padres", "Phillies", "Pirates", "Rangers", 
"Rays", "Red Sox", "Reds", "Rockies", "Royals", "Tigers", "Twins", 
"White Sox", "Yankees"), class = "factor"), GamesPlayed = c(162L, 
162L, 162L, 162L, 162L, 162L, 162L, 162L, 162L, 162L), CurrentWins = c(92L, 
75L, 83L, 85L, 101L, 91L, 93L, 80L, 86L, 66L)), .Names = c("Team", 
"GamesPlayed", "CurrentWins"), row.names = c(NA, 10L), class = "data.frame")
# create a GET request for shareprices (in JSON format)
#* @get /shareprices_json
getSPs <- function(){ 
return(toJSON(mydata))
}
# create a GET request for MLB shareprices (in CSV format)
#* @get /shareprices_csv
csvSPs <- function(){
return(mydata)
}
# run both functions (i think needed for the endpoints to work)   
getSPs()
csvSPs()

RunAPI.R:plumb的setupAPI.R,获取本地托管的端点

library(plumber)
r <- plumb("setupAPI.R") 
r$run(port=8000)

. . .

在控制台中运行 RunAPI.R 代码后,当我转到终结点时,我的 http://127.0.0.1:8000/shareprices_csv 终结点显然返回了一个 JSON 对象,而我的 http://127.0.0.1:8000/shareprices_json 终结点似乎奇怪地返回了长度为 1 的 JSON,字符串中的 JSON 作为返回的 JSON 中的唯一元素。

简而言之,我现在可以看到我应该简单地返回数据帧,而不是 toJSON(数据帧),以使端点托管 JSON 格式的数据,但我仍然不知道如何以 CSV 格式提供这些数据。这在水管工中可能吗?返回语句在setupAPI.R中的函数中应该是什么样子的?任何帮助不胜感激!!

如果对任何人有帮助,只需发布此答案!

Jeff 的响应效果很好,但是当您必须返回一个大的 CSV 文件时,它会变得非常慢。我在使用 22 MB 文件时遇到了问题。

如果您之前在磁盘上编写 CSV,更快的解决方案是使用include_file函数(此处为文档):

举个例子:

#* @get /iris_csv
getIrisCsv <- function(req, res) {
filename <- file.path(tempdir(), "iris.csv")
write.csv(iris, filename, row.names = FALSE)
include_file(filename, res, "text/csv")
}

因此,这取决于您的用例:

  • 如果您要返回一个小的csv并且不想将其写入磁盘:请使用Jeff的解决方案
  • 如果您的 CSV 是中型或大型 (> 2MB),或者您已经在磁盘上拥有它:请使用include_file解决方案

希望对您有所帮助!

这里有两个技巧:

  1. 可以通过直接返回响应对象来绕过终结点上的序列化。更多文档在这里
  2. 您可以通过更改res$body来指定响应的正文。

可以将这两个想法结合起来,创建一个终结点,如下所示:

#' @get /data.csv
function(res) {
con <- textConnection("val","w")
write.csv(iris, con)
close(con)
res$body <- paste(val, collapse="n")
res
}

请注意,水管工免费为您做一些好事,例如为您的 JSON 响应设置适当的 HTTP 标头。如果您自己发送响应,则所有这些操作都由您自己完成,因此您需要确保设置适当的标头来指导 API 客户端如何解释此响应。

最新更新