使用 jsonlite 解析带有数字标签的 json 字符串

Using jsonlite to parse json string with number labels

我正在从 API(我无法控制)中检索 json 字符串,如下所示:

{
     "data": [
     {
         "6": {
             "value": "Jamie Stein"
         },
         "7": {
             "value": 10
         }
     },
     {
         "6": {
             "value": "Bill Smith"
         },
         "7": {
             "value": 23
         }
     }
     ],
     "fields": [
     {
         "id": 6,
         "label": "Full Name"
     },
     {
         "id": 7,
         "label": "Amount"
     }
     ]
 }

我正在使用 jsonlite 包(版本 1.7.0)中的 fromJSON 来解析字符串: res <- from JSON(jsonstr).

生成的 data 数据帧的名称已损坏。结果如下所示:

> res
$data
        value value
1 Jamie Stein    10
2  Bill Smith    23

$fields
  id     label
1  6 Full Name
2  7    Amount

注意 data 数据框中的“值”列名称。我可以更新 data 数据框的列名,但这似乎让事情变得更奇怪了:

> get_label <- function(x) { res$fields$label[res$fields$id == x]}
> names(res$data) <- sapply(as.integer(names(res$data)), get_label)
> names(res$data)
[1] "Full Name" "Amount"   
> res$data
        value value
1 Jamie Stein    10
2  Bill Smith    23

names函数表明列名已更新,但仅打印数据帧表明列名仍然损坏。

有人可以帮助我了解正在发生的事情以及我可以做些什么吗?在这一点上我很困惑。损坏的数据帧有问题 - 当我使用 write.csv 时,生成的文件是垃圾文件。

此外,如果有帮助,我 运行 的 R 版本是 4.0.2。

嗯,奇怪。你可以这样做:

library(jsonlite)
library(purrr) # to use 'transpose'
obj <- fromJSON(json, simplifyDataFrame = FALSE)
lapply(obj, function(x){
  as.data.frame(lapply(transpose(x), unlist))
})
# $data
#            X6 X7
# 1 Jamie Stein 10
# 2  Bill Smith 23
# 
# $fields
#   id     label
# 1  6 Full Name
# 2  7    Amount

获取列名 "6""7":

lapply(obj, function(x){
  as.data.frame(lapply(transpose(x), unlist), check.names = FALSE)
})
# $data
#             6  7
# 1 Jamie Stein 10
# 2  Bill Smith 23
# 
# $fields
#   id     label
# 1  6 Full Name
# 2  7    Amount

编辑:更简单的方法

其实并不奇怪...

obj <- fromJSON(json)

obj$data 是一个数据框,但它的列也是数据框:

> str(obj$data)
'data.frame':   2 obs. of  2 variables:
 $ 6:'data.frame':  2 obs. of  1 variable:
  ..$ value: chr  "Jamie Stein" "Bill Smith"
 $ 7:'data.frame':  2 obs. of  1 variable:
  ..$ value: int  10 23

那么你想要:

obj$data <- as.data.frame(lapply(obj$data, "[[", "value"))