【问题标题】:encoding a JSON expression from R with jsonlite or something else用 jsonlite 或其他东西从 R 编码一个 JSON 表达式
【发布时间】:2016-04-19 22:47:15
【问题描述】:

我正在使用的 API 需要我向其发送 JSON 消息,例如:

y <- '[{"a":1, "b":"select", "c":["A", "B", "C"]}, 
       {"a":2, "b":"text"},
       {"a":3, "b":"select", "c":["D", "E", "F", "G"]}]'

请注意,在 "b" : "select" 的情况下,还有另一个变量 c,其值为数组。

当我尝试运行fromJSON(y)(在jsonlite 包中)时,我得到一个data.frame,其中第三列是一个列表:

> z <- fromJSON(y) 
> class(z)
[1] "data.frame"
> z %>% glimpse()
Observations: 3
Variables: 3
$ a (int) 1, 2, 3
$ b (chr) "select", "text", "select"
$ c (list) A, B, C, NULL, D, E, F, G

但是当我将它转换回JSON (这是我要发送到API 的格式)时,c 变量出现在不应该出现的位置。

[{"a":1,"b":"select","c":["A","B","C"]},
 {"a":2,"b":"text","c":{}},
 {"a":3,"b":"select","c":["D","E","F","G"]}]

是否有另一种 R 数据结构可以使用 jsonlite(或其他东西)可靠地将我从数据帧获取到原始 JSON 消息?它是如何工作的?

【问题讨论】:

  • 我认为如果你使用RJSONIO:fromJSON 然后jsonlite::toJSON 你会得到你想要的。

标签: json r dataframe jsonlite


【解决方案1】:

使用jsonlite,您可以执行以下操作:

z <- fromJSON(y, simplifyDataFrame = F)
toJSON(z, auto_unbox=T)

此外,考虑以下情况,最后一个c 元素是["D"]

y2 <- '[{"a":1, "b":"select", "c":["A", "B", "C"]}, 
        {"a":2, "b":"text"}, 
        {"a":3, "b":"select", "c":["D"]}]'

z2 <- fromJSON(y2, simplifyDataFrame = F)
toJSON(z2, auto_unbox=T)

结果是这样的:

[{"a":1,"b":"select","c":["A","B","C"]},
 {"a":2,"b":"text"},
 {"a":3,"b":"select","c":"D"}]

这可能很麻烦,因为最后一个 c 元素是 "D" 而不是 ["D"]

为防止这种情况,请不要使用auto_unbox。谨慎使用unbox,如下:

z2 <- fromJSON(y2, simplifyDataFrame = F)
for(i in 1:length(z2)){
  z2[[i]][[1]] <- unbox(z2[[i]][[1]])
  z2[[i]][[2]] <- unbox(z2[[i]][[2]])
}
toJSON(z2)

【讨论】:

  • 哦,这对我来说也是新的!学到了一些东西:D
  • 这是一个很好的提示 - 我已经为这个问题苦苦挣扎了很长时间。
【解决方案2】:

如果你需要一个数据框来计算东西,你可以这样做(rmNullObs函数来自here):

z <- fromJSON(y)

is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))

## Recursively step down into list, removing all such objects 
rmNullObs <- function(x) {
  x <- Filter(Negate(is.NullOb), x)
  lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}    

z_list <- rmNullObs(as.list(as.data.frame(t(z))))
toJSON(unname(z_list), auto_unbox=T)

这会将数据帧转换为列表,删除 NULL,然后转换回 JSON。

如果您不需要数据框,请参阅@skwon 的回答

【讨论】:

  • 这听起来像我正在寻找的东西,但我从您的代码中得到:{"1":{"a":1,"b":"select","c":["A","B","C"]},"2":{"a":2,"b":"text"},"3":{"a":3,"b":"select","c":["D","E","F","G"]}} 。我需要外部数据结构是一个数组。
  • 忘记unname 列表,已修复。
猜你喜欢
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多