httr与httr2调用API的输出差异及httr2格式优化方案
问题:httr2解析IMF API结果与httr+jsonlite不一致的原因及解决办法
我们分别用httr和httr2调用IMF的API,代码如下:
library(httr) library(httr2) library(jsonlite) library(tidyverse) # httr 实现 resp<- GET("http://dataservices.imf.org/REST/SDMX_JSON.svc/Dataflow") %>% content(as = "text", encoding = "UTF-8") %>% fromJSON() imf_datasets1 <- resp$Structure$Dataflows$Dataflow # httr2 实现 req <- request("http://dataservices.imf.org/REST/SDMX_JSON.svc/Dataflow") resp1 <- req |> req_perform() parsed_body <- resp_body_json(resp1) imf_datasets2 <- parsed_body$Structure$Dataflows$Dataflow %>% as.data.frame()
两次调用指向同一API端点,但输出的数据框imf_datasets1和imf_datasets2结构差异明显:httr结合jsonlite得到的数据框格式规整,无需额外处理;而httr2解析后转成的数据框结构混乱。
原因解析
resp_body_json()默认调用jsonlite::fromJSON(simplifyVector = FALSE),这个参数会保留JSON的原始嵌套结构,不会自动将嵌套数组简化为数据框。而你用httr时直接调用的jsonlite::fromJSON()默认参数是simplifyVector = TRUE,会自动识别符合数据框结构的嵌套JSON,并将其转换为规整的数据框格式。
解决办法
有两种方式可以让httr2得到和imf_datasets1完全一致的整洁数据框:
方法一:修改resp_body_json的参数
在resp_body_json()中显式设置simplifyVector = TRUE,让它和jsonlite默认行为保持一致:
req <- request("http://dataservices.imf.org/REST/SDMX_JSON.svc/Dataflow") resp1 <- req |> req_perform() parsed_body <- resp_body_json(resp1, simplifyVector = TRUE) imf_datasets2 <- parsed_body$Structure$Dataflows$Dataflow
方法二:手动用jsonlite解析响应文本
先把响应转为文本格式,再直接调用jsonlite::fromJSON()解析,完全复刻httr的处理逻辑:
req <- request("http://dataservices.imf.org/REST/SDMX_JSON.svc/Dataflow") resp1 <- req |> req_perform() resp_text <- resp_body_string(resp1) parsed_body <- jsonlite::fromJSON(resp_text) imf_datasets2 <- parsed_body$Structure$Dataflows$Dataflow
内容的提问来源于Stack Exchange,提问作者chris_chris
相关产品推荐
相关产品推荐

