用 jsonlite 或其他东西从 R 编码 JSON 表达式
encoding a JSON expression from R with jsonlite or something else
我正在使用的 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
,其中第 3 列是一个列表:
> 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
消息?它是如何工作的?
与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)
如果你需要一个数据框来计算东西,你可以这样做(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 的回答
我正在使用的 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
,其中第 3 列是一个列表:
> 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
消息?它是如何工作的?
与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)
如果你需要一个数据框来计算东西,你可以这样做(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 的回答