【问题标题】:R httr POST of JSON returns status 400JSON的R httr POST返回状态400
【发布时间】:2014-05-16 22:21:54
【问题描述】:

我正在开发一些函数来从StatBank Denmark 和他们的API 获取数据。他们制作了console 来测试 JSON 调用,我知道我在 dst_get_data 函数中解析为 JSON 的 basic_request 有效,因为我已经在控制台中对其进行了测试。

我收到“状态 400”错误和一条错误消息,提示我应该“在发布时提供对象”。

下面的代码应该是可重现的示例。这是我卡住的第三个函数(dst_get_data)。

dst_meta <- function(table, ..., lang = "en"){
  require(jsonlite)
  require(httr)

  dkstat_url <- "http://api.statbank.dk/v1/tableinfo"

  params <- list("lang" = lang,
                 "table" = table,
                 "format" = "JSON")

  meta <- POST(url=dkstat_url, body=params, multipart=FALSE)
  meta <- jsonlite::fromJSON(txt=content(meta, as="text"),simplifyDataFrame=TRUE)
  #meta <- RJSONIO::fromJSON(content=content(meta),asText=TRUE, simplify=TRUE, simplifyWithNames=TRUE)

  return(meta)
}

dst_meta_parse <- function(meta, lang){

  basics_names <- c("id", "text", "description", 
                    "unit", "updated", "footnote")

  basics <- meta[names(meta) %in% basics_names]

  variables <- meta[["variables"]][,c("id", "text")]

  values <- meta[["variables"]][,"values"]
  names(values) <- variables$id

  if(lang == "en"){
    test <- grepl(pattern="Tid", names(values))
    if(sum(test) > 0){
      values$Tid$id <- sub(pattern="Q", replacement="K", x=values$Tid$id)
    }
  }

  ## Create basic_request for the data_post file
  basic_request <- vector(mode="list", length=length(variables$id))
  for(variable in 1:length(variables$id)){

    var_name <- variables$id[variable]

    if(var_name == "Tid"){
      basic_request[[variable]] <- list("code" = var_name,
                                       "values" = as.character(values[[var_name]]$id[length(values[[var_name]]$id)]))
    } else {
      basic_request[[variable]] <- list("code" = var_name,
                                       "values" = as.character(values[[var_name]]$id[1]))
    }
  }
  return(list("basics" = basics, "variables" = variables, "values" = values, "basic_request" = basic_request))
}

dst_get_data <- function(request, table,..., lang = "en", format = "CSV", value_presentation = "Default"){
  require(httr)
  require(jsonlite)

  dst_url <- "http://api.statbank.dk/v1/data"

  final_request <- list("table" = table,
                        "lang" = lang,
                        "format" = format,
                        "valuePresentation" = value_presentation,
                        "variables" = request)

  final_request <- jsonlite::toJSON(x=final_request, .escapeEscapes=TRUE, asIs=TRUE)
  print(validate(final_request))
  data <- POST(url=dst_url, body=final_request, multipart=FALSE)

  return(data)
}

test <- dst_meta(table="folk1")

test2 <- dst_meta_parse(meta = test, lang = "en")

test3 <- dst_get_data(request = test2$basic_request, table = "folk1", format="JSON")
#test3 <- dst_get_data(request = test2$basic_request, table = "folk1", format="JSON")

【问题讨论】:

  • 您有计划将此代码作为一个包公开吗?
  • @Thomas 是的,我已经考虑过了。但我昨天才开始,所以不是现在的形式。这是我的第一个包,所以最初只是在 github 上(我只需要赶上一些介绍材料)。
  • 酷。如果您需要帮助,请告诉我(我在 Github 上是 leeper)。我认为这样的包裹可能会引起人们的兴趣。
  • 谢谢!我会及时通知你。

标签: json r httr rjsonio jsonlite


【解决方案1】:

当我将dst_get_data 更改为:

dst_get_data <- function(request, table, ..., lang = "en", 
                         format = "CSV", value_presentation = "Default") {

  require(httr)
  require(jsonlite)

  dst_url <- "http://api.statbank.dk/v1/data"

  final_request <- list("table" = table,
                        "lang" = lang,
                        "format" = format,
                        "valuePresentation" = value_presentation)

  data <- POST(url=dst_url, body=final_request, multipart=FALSE)

  return(data)

}

并且,对它的调用:

test3 <- dst_get_data(request = test2$basic_request, 
                      table = "folk1", format="JSONSTAT")

我明白了:

Response [http://api.statbank.dk/v1/data]
  Status: 200
  Content-type: text/json
{"dataset":{"dimension":{"Tid":{"label":"time","category":{"index":{"2014K2":0},"label":{"2014K2":"2014Q2"}}},"id":["Tid"],"size":[1],"role":{"time":["Tid"]}},"label":"Population at the first day of the quarter by time","source":"Statistics Denmark","updated":"2014-05-17T04:10:00Z","value":[5634437],"status":["a"]}} 

我认为这既是对JSONSTAT 的需求,也是POST 会自动为您进行JSON 转换的事实。您需要JSONSTAT 的原因是因为“格式”可用当您从弹出窗口(在控制台中)选择data 时:

<select id="format" name="format"><option value="PX">PX</option>
<option selected="selected" value="CSV">CSV</option>
<option value="XLSX">XLSX</option>
<option value="HTML">HTML</option>
<option value="JSONSTAT">JSONSTAT</option>
<option value="DSTML">DSTML</option>
<option value="PNG">PNG</option>
<option value="BULK">BULK</option>
<option value="AREMOS">AREMOS</option>
<option value="SDMXCOMPACT">SDMXCOMPACT</option>
<option value="SDMXGENERIC">SDMXGENERIC</option>
</select>

Plain ol' JSON 不是选项之一。

【讨论】:

  • 我想知道为什么我的 POST 不能使用 JSON?!在我看来,@hadley 正在这里做 https://github.com/hadley/httr/blob/master/vignettes/api-packages.Rmd 感谢您的指点!
  • 我用JSONSTAT 的原因更新了答案。自动转换为 JSON 可能是最近添加的(因此与 Hadley 的示例不同)。
  • 编辑:删除评论,因为我没有仔细查看回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
  • 2020-07-23
相关资源
最近更新 更多