我正在尝试从API读取JSON元数据,在R中对其进行操作,然后回发。
但是,当我通过jsonlite获取元数据时,TRUE / FALSE值将被读取为逻辑值并变为大写。该API将不接受大写的TRUE / FALSE。因此,我需要将所有TRUE / FALSE替换为字符“ true”和“ false”,但保留与输入相同的嵌套列表结构。
问题在于这些是JSON键/值对和嵌套数组,因此true / false值嵌套在不同级别。我也只想更改“ TRUE”或“ FALSE”的值,而不更改包含“ true”或“ false”的字符串。
我尝试应用函数系列,purrr映射和递归循环。
#read data via API
dashitem_api<-paste0("api/metadata.json?filter=id:like:",dashitem_old_idprefix)
url<-paste0(baseurl,dashitem_api)
dash_items<-jsonlite::fromJSON(content(GET(url),"text")[])
...然后替换ID ....
编辑: ID的替换是将逻辑TRUE / FALSE值强制转换为字符串“ true” /“ false”。
详细说明的道歉...
dashitem_old_idprefix<-"Ane0008"
dashitem_new_idprefix<-"Ane0028"
dash_items<-jsonlite::fromJSON(content(GET(url),"text")[])
class(dash_items$charts$showData)
###output = "logical"
#put all the replacement items into a list
x1<-list(dashitem_old_idprefix,
dashitem_new_idprefix)
x2<-sapply(x1, function(x) as.character(x))
replacements<-function(y){
return(
y %>%
gsub(x2[1], x2[2], .)
)
}
new_dash <- rapply(dash_items, f = replacements,
how = "replace")
class(new_dash$charts$showData)
###output = "character"
R对象是一个列表,包含字符向量,命名列表,未命名列表,字符向量列表和数据帧,类似这样的
new_dash<-list(charts=list(list(id="abcd123",shared="FALSE",translations=list(),
dimensions=data.frame(thisyear="FALSE",last6Months="TRUE"),
params=list(reportingPeriod="FALSE",reportingUnit="FALSE"),
dimensionItems=list(type="DATA_ELEMENT",dataElement=list(id="ZYXW987"))),
list(id="abcd4567",shared="FALSE",translations=list(),
dimensions=data.frame(thisyear="FALSE",last6Months="TRUE"),
params=list(reportingPeriod="FALSE",reportingUnit="TRUE"),
dimensionItems=list(type="DATA_ELEMENT",dataElement=list(id="ZYXW988")))),
reportTables=list(id="abcd124",title="false positives", shared="FALSE",translations=list(),
dimensions=data.frame(thisyear="FALSE",last6Months="TRUE"),
params=list(reportingPeriod="FALSE",reportingUnit="FALSE"),
dimensionItems=list(type="DATA_ELEMENT",dataElement=list(id="ZYXW989"))))
我在网上找到了这些解决方案,但是我发现我需要使用真/假数据值指定列表的名称或位置,否则会出现错误,或者它以不需要的方式更改了new_dash文件(添加了新的嵌套列表)。
#solution 1
change_list <- function(x) {
for (i in seq_along(x)) {
value <- x[[i]]
if (is.list(value)) {
x[[i]] <- change_list(value)
} else {
if (as.character(value)=="FALSE") {
x[[i]] <- tolower(value)
}
}
}
x
}
test1<-change_list(new_dash)
#solution 2
test2<-lapply(new_dash, function(x) {
id <- x == "FALSE"
x[id] <- "false"
return(x)
})
#solution 3
test3<- c(map(new_dash$charts,
~modify_if(~x=="TRUE", tolower)),
recursive= TRUE)
我可能需要结合purify_if和Modify_at的purrr函数。或者,这是一种读取默认情况下不会转换为逻辑TRUE / FALSE的数据的替代方法。
FWIW,我是R新手,无论回答多么复杂或简单,我都会感谢您。
答案 0 :(得分:1)
列表对象中的值实际上是"TRUE"
(R字符串)还是TRUE
(R逻辑)?如果它们是有效的R逻辑(与您共享的示例数据不同),那么jsonlite::toJSON
将对其进行更正。
x <- list(
partA = list(numbers = 1:3, boolean = T),
partB = list(
nested = list(
numbers = 4:6,
nestB = list(boolean = c(FALSE, FALSE))
)
)
)
jsonlite::toJSON(x, pretty = T)
{ "partA": { "numbers": [1, 2, 3], "boolean": [true] }, "partB": { "nested": { "numbers": [4, 5, 6], "nestB": [ { "boolean": false }, { "boolean": false } ] } } }
您似乎不太可能在数据处理步骤中生成"TRUE"
和"FALSE"
的字符串(已更新: 实际上是问题所在! ),因此希望它能奏效。 jsonlite::fromJSON
将[true, false]
转换为c(TRUE, FALSE)
,而toJSON
则相反。
确保将数据帧强制转换为相同格式可能需要进行一些检查。 toJSON
有一些选择:dataframe =
可以
"nestB": {"boolean": [false, false]}
或"nestB": [[false], [false]]
但是,如果您使用默认值来读取API响应,则不太可能需要更改默认值以将其发送回去。
此用例正在调用rapply
来搜索整个列表对象并替换某些元素。因为那是在调用gsub
,所以每个元素都被强制为一个字符,包括任何数字或逻辑值。为防止这种情况,可以使用some_output_object <- rapply(some_input_object, f = some_replacing_function, how = "replace", classes = "character")
。这样就不会保留数字和逻辑值,因此toJSON
可以正确地将它们包装起来。