在R:400错误请求

时间:2016-09-20 13:54:28

标签: json r post rcurl httr

我试图从网络API中获取R中的数据(推断媒体,具体)

我的案例中的GET请求已成功处理。但是,POST有问题

请求包含数据,这些数据将被处理并随后返回。这两种都是json格式。

api文档中的示例代码如下:

    curl -v -X GET "https://api.infermedica.com/v2/symptoms"

使用curl在R中执行此操作,我使用:

    h <- new_handle()
    handle_setheaders(h, 'app_id' = "id", 'app_key' = "key", 'Accept' = "application/json" )
    curl_fetch_memory("https://api.infermedica.com/v2/symptoms", handle = h)

这只能发送标题。但是,对于POST主体这样的复杂请求,我觉得我最好不要使用httr,我找不到使用curl发送身体数据的方法

使用httr执行的相同查询如下:

    GET(url = "https://api.infermedica.com/v2/symptoms", verbose(),add_headers(app_id = "id", app_key = "key", 'Accept' = "application/json"))

这也有效。然后是POST请求

包含json的数据的文档代码如下所示:

    curl -v -X POST -H "Content-Type:application/json" "https://api.infermedica.com/v1/diagnosis" -d '{"sex": "male", "age": 29, "evidence": [ { "id": "s_21", "choice_id": "present" } ] }'

为此,我创建了我的json:

    bod <- list(sex = jsonlite::unbox('male'), age = jsonlite::unbox('26'), evidence = data.frame(id = "s_21", choice_id = 'present')) 

如果您注意到,证据信息将作为数据框创建。这样做的原因是,当我将其更改为json时,它看起来与文档中的文本json完全相同。这就是我的意思:

    POST(url = "https://api.infermedica.com/v1/diagnosis", body = bod  ,
      encode = 'json', verbose(),
     add_headers(app_id = "id", app_key = "key", 'Content-Type:' = "application/json"))

此请求的详细信息是:

  • POST / v1 /诊断HTTP / 1.1

    • 主持人:api.infermedica.com
    • User-Agent:libcurl / 7.47.0 r-curl / 1.2 httr / 1.2.1
    • 接受编码:gzip,deflate
    • 接受:application / json,text / xml,application / xml, /
    • Content-Type:application / json
    • app_id:id
    • app_key:key
    • Content-Type :: application / json
    • 内容长度:74
    • {&#34;性别&#34;:&#34;男性&#34;&#34;年龄&#34;:&#34; 26&#34;&#34;证据&#34 ;:[{&#34; ID&#34;:&#34; s_21&#34;&#34; choice_id&#34;:&#34;本&#34;}]}

    • HTTP / 1.1 400错误请求

    • 日期:2016年9月20日星期二13:26:46 GMT
    • Content-Type:application / json; charset = utf-8
    • 内容长度:25
    • 连接:keep-alive
    • X-Content-Type-Options:nosniff
    • X-Frame-Options:sameorigin
    • 服务器:Infermedica
    • Access-Control-Allow-Origin:*
    • Access-Control-Allow-Credentials:true
    • Access-Control-Allow-Methods:GET,POST,OPTIONS
    • Access-Control-Allow-Headers:DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,app_id,app_key

查看身体数据的行: -

{&#34;性别&#34;:&#34;男性&#34;&#34;年龄&#34;:&#34; 26&#34;&#34;证据&#34;:[ {&#34; ID&#34;:&#34; s_21&#34;&#34; choice_id&#34;:&#34;本&#34;}]}

api如何决定它应该是什么样的。

但是,但是,错误的请求错误被抛到我身上。 我尝试使用嵌套列表作为正文,但没有任何好处。从文档页面复制粘贴json字符串并将其传递给它也会产生相同的错误。 当然,当我从终端运行cURL命令时,请求会被处理,这意味着我将json数据传递给服务器的方式有问题

非常感谢任何帮助

1 个答案:

答案 0 :(得分:1)

这可能有助于您入门:

library(httr)
library(jsonlite)
library(dplyr)

im_info <- function() {

  res <- GET("https://api.infermedica.com/v2/info",
             add_headers(app_id=Sys.getenv("INFERMEDICA_APP_ID"),
                         app_key=Sys.getenv("INFERMEDICA_APP_KEY")))

  stop_for_status(res)

  content(res, as="text", encoding="UTF-8") %>% 
    fromJSON(flatten=TRUE)

}


im_list_symptoms <- function() {

  res <- GET("https://api.infermedica.com/v2/symptoms",
             add_headers(app_id=Sys.getenv("INFERMEDICA_APP_ID"),
                         app_key=Sys.getenv("INFERMEDICA_APP_KEY")))

  stop_for_status(res)

  content(res, as="text", encoding="UTF-8") %>% 
    fromJSON(flatten=TRUE)

}

im_get_symptom <- function(symptom_id="s_277") {

  res <- GET(sprintf("https://api.infermedica.com/v2/symptoms/%s", symptom_id),
             add_headers(app_id=Sys.getenv("INFERMEDICA_APP_ID"),
                         app_key=Sys.getenv("INFERMEDICA_APP_KEY")))

  stop_for_status(res)

  content(res, as="text", encoding="UTF-8") %>% 
    fromJSON(flatten=TRUE)

}


im_start_diagnosis <- function() {
  return(list(age=NULL, sex=NULL))
}

im_add_patient_info <- function(diag_obj, age, sex) {
  diag_obj$age <- unbox(as.numeric(age))
  diag_obj$sex <- unbox(sex)
  diag_obj
}

im_add_evidence <- function(diag_obj, id, choice=c('present', 'absent', 'unknown')) {

  choice <- match.arg(choice, c('present', 'absent', 'unknown'))

  df <- data_frame(id=id, choice_id=choice)

  if (length(diag_obj$evidence) == 0) {
    diag_obj$evidence <- df
  } else {
    bind_rows(diag_obj$evidence, df)
  }

  diag_obj

}

im_get_diagnosis <- function(diag_obj) {

  res <- POST("https://api.infermedica.com/v2/diagnosis",
              add_headers(app_id=Sys.getenv("INFERMEDICA_APP_ID"),
                          app_key=Sys.getenv("INFERMEDICA_APP_KEY")),
              body=diag_obj,
              encode="json",
              verbose())

  stop_for_status(res)

  content(res, as="text", encoding="UTF-8") %>% 
    fromJSON(flatten=TRUE)

}

im_start_diagnosis() %>% 
  im_add_patient_info(29, "male") %>% 
  im_add_evidence("s_21", "present") %>% 
  im_get_diagnosis()

您现在可以使用alpha包:infermedica