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

Using R's Plumber - create GET endpoint to host CSV formatted data rather than 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 endpoint is clearly returning a JSON object, and my http://127.0.0.1:8000/shareprices_json 端点似乎很奇怪 returning JSON 的长度为 1,字符串中的 JSON 作为 returned JSON 中的唯一元素。

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

这里需要两个技巧:

  1. 您可以通过直接返回响应 object 来绕过端点上的序列化。更多文档 here
  2. 您可以通过改变 res$body 来指定响应的 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 headers。如果您自己发送回复,则只能靠自己解决所有这些问题,因此您需要确保设置适当的 headers 来教导您的 API 客户他们应该如何解释这个回复。

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

Jeff 的响应非常完美,但是当您必须 return 一个大的 CSV 文件时,它会变得非常慢。我在处理一个 22 MB 的文件时遇到了问题。

一个更快的解决方案,如果你以前在磁盘上写入 CSV,是使用 include_file 函数(文档 here):

举个例子:

#* @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")
}

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

  • 如果您return正在处理一个小的 csv 并且不想将它写入磁盘:使用 Jeff 的解决方案
  • 如果您的 CSV 是中型或大型 (> 2MB) 或者您已经将其保存在磁盘上:使用 include_file 解决方案

希望对您有所帮助!