首页 > 解决方案 > 使用 jsonlite 解析带有数字标签的 json 字符串

问题描述

我正在从 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"
     }
     ]
 }

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

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

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

$fields
  id     label
1  6 Full Name
2  7    Amount

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

> 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。

标签: rjsonjsonlite

解决方案


嗯,奇怪。你可以做:

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"))

推荐阅读