2016-09-20 127 views
1

我試圖從Web API獲取的R數據(infermedia,具體而言)檢索數據:400錯誤的請求

在我的情況下,GET請求被處理成功。但是,POST有問題

請求包含數據,這些數據被處理並返回。這兩個都是json格式。從API文檔

示例代碼的樣子:

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

到R中使用curl執行此,我用:

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了,我無法找到一個方法只用捲曲

使用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
    • Accept-Encoding:gzip,deflate
    • 接受:應用/ JSON,文本/ XML的應用程序/ XML,/
    • 內容類型:應用程序/ JSON
    • APP_ID:ID
    • APP_KEY:關鍵
    • 內容類型::應用/ JSON
    • 的Content-Length:74
    • { 「性」: 「男」, 「年齡」: 「26」, 「證據」:[{ 「ID」: 「s_21」, 「choice_id」:」目前「}]}

    • HTTP/1。1 400錯誤的請求

    • 日期:星期二,2016年9月20日13點26分46秒GMT
    • 內容類型:應用/ JSON;字符集= UTF-8
    • 的Content-Length:25
    • 連接:保活
    • X-Content-Type的選項:nosniff
    • X框選項:SAMEORIGIN
    • 服務器:Infermedica
    • 訪問控制允許來源:*
    • 訪問控制允許的憑據:真
    • 訪問控制允許的方法:GET,POST,OPTIONS
    • 訪問控制允許報頭:DNT,X-MX-ReqToken,保持活動,用戶代理,X-請求-隨着,如果-Modified-Since的,高速緩存控制,內容類型,APP_ID,APP_KEY

看到與主體數據的行: -

{ 「性別」:「男性」,「年齡」:「26」,「證據」:[{「id」:「s_21」,「choice_id」:「present」}]}

究竟api是如何規定它應該看起來像。

但是,不好的請求錯誤引發了我。 我嘗試使用嵌套列表的身體,這沒有任何好處。從文檔頁複製粘貼json字符串並將其作爲它傳遞也會產生相同的錯誤。當我從終端運行卷曲的命令,當然,這意味着有一些錯誤的方式我傳遞JSON數據到服務器

任何幫助,將不勝感激

+1

您的問題是:'年齡= jsonlite ::拆箱(「26」)'你傳遞一個API等待數字的字符串(您的c url json有一個沒有引用的26)。刪除26左右的引號,你應該沒問題。 – Tensibai

+0

@Tensibai我也嘗試過,不幸的是,它仍然會拋出同樣的錯誤,我也有你的內容類型標題的兩倍 – rangeelo

+1

。嘗試從add_header調用 – Tensibai

回答

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