在R中使用httr POST到API会导致错误

时间:2018-08-02 23:50:28

标签: r post httr jsonlite

我正在尝试使用httr包将数据直接从API提取到R中。该API不需要任何身份验证,并且接受lat,long,海拔,变量集和时间段的JSON字符串来估计任何位置的气候变量。这是我第一次使用API​​,但是下面的代码是我从各种Stack Overflow帖子中拼凑而成的。

library(jsonlite)
library(httr)    
url = "http://apibc.climatewna.com/api/clmApi"
body <- data.frame(lat = c(48.98,50.2), ##two example locations
                   lon = c(-115.02, -120),
                   el = c(1000,100),
                   prd = c("Normal_1961_1990.nrm","Normal_1961_1990.nrm"),
                   varYSM = c("Y","SST"))
requestBody <- toJSON(list("output" = body),auto_unbox = TRUE) ##convert to JSON string

result <- POST("http://apibc.climatewna.com/api/clmApi", ##post to API
               body = requestBody,
               add_headers(`Content-Type`="application/json"))
content(result)

我尝试了各种不同的版本(例如,手动编写JSON字符串,使用encode = "json"将正文作为列表放置在POST中),它始终运行,但是内容始终包含以下错误消息:

$Message
[1] "An error has occurred."

$ExceptionMessage
[1] "Object reference not set to an instance of an object."

$ExceptionType
[1] "System.NullReferenceException"

如果我使用GET并直接在URL中指定变量

url = "http://apibc.climatewna.com/api/clmApi/LatLonEl?lat=48.98&lon=-115.02&el=1000&prd=Normal_1961_1990&varYSM=Y"
result <- GET(url)
content(result)

它会产生正确的输出,但是我一次只能获得一个位置的信息。目前尚无关于此API的公开文档,因为它很新,但是我在下面附上了使用JS对其进行解释的部分草稿。enter image description here非常感谢您对我所提供的帮助/建议。我做错了! 谢谢!

1 个答案:

答案 0 :(得分:0)

主要问题是<!-- The form that I need to post --> <!DOCTYPE html> <html> <head> <title>PublicFiles - Register</title> </head> <body> <h1>Register</h1> <form action="process.php" method="post"> <input type="text" name="uname" placeholder="Screen Name..."><br> <input type="password" name="pword" placeholder="Password..."><br> <input type="email" name="email" placeholder="Email..."><br> <input type="submit" value="Sign Up"> </form> </body> </html>在将数据发送到API之前使用jQuery.ajax对数据进行编码,因此它发送的内容类似于jQuery.param。我不知道R中的某个程序包的编码与[0][lat]=48.98&[0][lon]=-115.02...类似,所以我们必须一起破解一些东西。

稍微修改您的示例:

jQuery.param

现在,我们进行编码,就像这样:

library(httr)
body <- data.frame(lat = c(48.98,50.2), ##two example locations
                   lon = c(-115.02, -120),
                   el = c(1000,100),
                   prd = c("Normal_1961_1990","Normal_1961_1990"),
                   varYSM = c("Y","Y"))

所以现在out <- sapply(1:nrow(body), function(i) { paste(c( paste0(sprintf("[%d][lat]", i - 1), "=", body$lat[i]), paste0(sprintf("[%d][lon]", i - 1), "=", body$lon[i]), paste0(sprintf("[%d][el]", i - 1), "=", body$el[i]), paste0(sprintf("[%d][prd]", i - 1), "=", body$prd[i]), paste0(sprintf("[%d][varYSM]", i - 1), "=", body$varYSM[i]) ), collapse = "&") }) out <- paste(out, collapse = "&") 是API所喜欢的形式。最后

out

注意result <- POST(url = "http://apibc.climatewna.com/api/clmApi", ##post to API body = out, add_headers(`Content-Type`="application/x-www-form-urlencoded")) 。我们得到

Content-Type