API调用问题

时间:2018-09-26 05:51:43

标签: r post httr

我正在尝试使用以下方法将一些数据点发送到Web api。 (不确定是否要共享密钥,因此我将其中的一部分遗漏了。)

library(jsonlite)
library(httr)

url = "https://api.marketcycles.online/api/CycleScanner"
t <- 1:101
val <- 2*sin(2*pi*t/25) + 5*cos(2*pi*t/50)
val[1:3]
body.list <- list(datapoints = val)
query.list <- list(api_Key = "wtt****")
res <- POST(url = url, query = query.list, body = body.list,
            encode = "json")
a <- content(res, as = "text")
b <- fromJSON(a)
b[[2]]

这将导致错误“对象引用未设置为对象的实例”

以下curl命令有效(我已经编辑了大部分数据点)

curl -X POST --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    -d '[5.458,5.8064,6.018,....5,5.458]' \
    'https://api.marketcycles.online/api/CycleScanner?api_Key=wtt****'

关于使POST命令起作用的任何建议吗?

感谢您的回答hrbrmstr。非常感激。 我尝试了以下

httr::POST(
  url = "https://api.marketcycles.online/api/CycleScanner",
  httr::content_type_json(),
  httr::accept_json(),
  encode = "json", 
  body = jsonlite::toJSON(val),
  query = list(
    amplitudeMulti = "1.0",
    bartelsLimit = "49",
    minCycleLength = "5",
    maxCycleLength = "300",
    sortByStrength = "true",
    includeSpectrum = "false",
    humanReadableText = "false",
    api_Key = "wtt****")
)

带有和不带有content_type_jason()的行,并且在两种情况下都收到以下错误

b[[1]]
[1] "The request contains an entity body but no Content-Type header. The
inferred media type 'application/octet-stream' is not supported for this
resource."
b[[2]]
[1] "No MediaTypeFormatter is available to read an object of type
'Double[]' from content with media type 'application/octet-stream'."
b[[3]]
[1] "System.Net.Http.UnsupportedMediaTypeException"

据我了解,当主体是列表时,encode()提供列表元素的格式。我不清楚在不这样做时该怎么办。我查看了httr源,其中有一个未记录的函数body_config,但不确定在POST命令中使用它。有解决此问题的建议吗?

2 个答案:

答案 0 :(得分:0)

我没有API密钥(并且您100%正确地共享您的密钥),但是他们的Swagger API Docs有点说谎他们期望作为输入。

我在他们提供的在线Swagger测试器中对该端点使用了伪造的API密钥(知道它会失败,但仍显示curl行),并填充了默认值,以全面了解端点的期望并把它退了回来(格式化是我的,它回来了整整一行):

curl 
  -X POST 
  --header 'Content-Type: application/json' 
  --header 'Accept: application/json' 
  -d '[5.458,5.8064,6.018,6.0702,5.9472,5.6409,5.1517,4.4888,3.6699,2.7207,1.6732,0.5646,-0.5646,-1.6732,-2.7207,-3.6699,-4.4888,-5.1517,-5.6409,-5.9472,-6.0702,-6.018,-5.8064,-5.458,-5,-4.4632,-3.8794,-3.2798,-2.6929,-2.143,-1.6488,-1.2225,-0.8695,-0.5879,-0.3695,-0.2007,-0.0633,0.0633,0.2007,0.3695,0.5879,0.8695,1.2225,1.6488,2.143,2.6929,3.2798,3.8794,4.4632,5,5.458,5.8064,6.018,6.0702,5.9472,5.6409,5.1517,4.4888,3.6699,2.7207,1.6732,0.5646,-0.5646,-1.6732,-2.7207,-3.6699,-4.4888,-5.1517,-5.6409,-5.9472,-6.0702,-6.018,-5.8064,-5.458,-5,-4.4632,-3.8794,-3.2798,-2.6929,-2.143,-1.6488,-1.2225,-0.8695,-0.5879,-0.3695,-0.2007,-0.0633,0.0633,0.2007,0.3695,0.5879,0.8695,1.2225,1.6488,2.143,2.6929,3.2798,3.8794,4.4632,5,5.458]' 
  'https://api.marketcycles.online/api/CycleScanner?amplitudeMulti=1.0&bartelsLimit=49&minCycleLength=5&maxCycleLength=300&sortByStrength=true&includeSpectrum=false&humanReadableText=false&api_Key=aaaa'

这表明文档在暗示datapoints值被命名时在撒谎。不是。这可能是导致您出错的原因。

我通过curlconverter运行了生成的原始curl命令行,并将其作为httr模板提供了

httr::VERB(
  verb = "POST", 
  url = "https://api.marketcycles.online/api/CycleScanner",
  httr::add_headers(Accept = "application/json"),
  body = "[5.458,5.8064,6.018,6.0702,5.9472,5.6409,5.1517,4.4888,3.6699,2.7207,1.6732,0.5646,-0.5646,-1.6732,-2.7207,-3.6699,-4.4888,-5.1517,-5.6409,-5.9472,-6.0702,-6.018,-5.8064,-5.458,-5,-4.4632,-3.8794,-3.2798,-2.6929,-2.143,-1.6488,-1.2225,-0.8695,-0.5879,-0.3695,-0.2007,-0.0633,0.0633,0.2007,0.3695,0.5879,0.8695,1.2225,1.6488,2.143,2.6929,3.2798,3.8794,4.4632,5,5.458,5.8064,6.018,6.0702,5.9472,5.6409,5.1517,4.4888,3.6699,2.7207,1.6732,0.5646,-0.5646,-1.6732,-2.7207,-3.6699,-4.4888,-5.1517,-5.6409,-5.9472,-6.0702,-6.018,-5.8064,-5.458,-5,-4.4632,-3.8794,-3.2798,-2.6929,-2.143,-1.6488,-1.2225,-0.8695,-0.5879,-0.3695,-0.2007,-0.0633,0.0633,0.2007,0.3695,0.5879,0.8695,1.2225,1.6488,2.143,2.6929,3.2798,3.8794,4.4632,5,5.458]",
  encode = "json", 
  query = list(
    amplitudeMulti = "1.0",
    bartelsLimit = "49",
    minCycleLength = "5",
    maxCycleLength = "300",
    sortByStrength = "true",
    includeSpectrum = "false",
    humanReadableText = "false",
    api_Key = "aaaa"
  )
)

它比以编程方式生成的必需b / c更为冗长。使其适合您的原始代码:

httr::POST(
  url = "https://api.marketcycles.online/api/CycleScanner",
  httr::accept_json()
  encode = "json", 
  body = jsonlite::toJSON(val),
  query = list(
    amplitudeMulti = "1.0",
    bartelsLimit = "49",
    minCycleLength = "5",
    maxCycleLength = "300",
    sortByStrength = "true",
    includeSpectrum = "false",
    humanReadableText = "false",
    api_Key = "aaaa"
  )
)

可能有效。同样,我只是经过Swagger而无法对其进行测试。您也可以在query位中删除所有默认值。我喜欢在构建与API接口的软件包时传递它们。

答案 1 :(得分:0)

找到了解决方案。这是hrbrmstr建议的代码的几处调整。 以下代码有效

httr::POST(
  url = "https://api.marketcycles.online/api/CycleScanner",
  httr::content_type_json(), # needed to add this
  httr::accept_json(),
  body =jsonlite::toJSON(val),
  # encode = "json", # needed to delete this 
  query = list(
    amplitudeMulti = "1.0",
    bartelsLimit = "49",
    minCycleLength = "5",
    maxCycleLength = "300",
    sortByStrength = "true",
    includeSpectrum = "false",
    humanReadableText = "false",
    api_Key = "wtt****")
)

感谢您的帮助。