Rでtibble(data.frame)からネストされたjsonを出力する
tibble to nested json
などで検索するといろいろな方法出てきますが、一番スマートなのは tidyr::nest()
でネストしたtibbleを jsonlite::toJSON()
でjsonに変換するやり方かと思います。
セッション情報
諸事情あってRStudioDesktopで動かしています。
> sessionInfo() R version 4.0.2 (2020-06-22) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows >= 8 x64 (build 9200) Matrix products: default locale: [1] LC_COLLATE=Japanese_Japan.932 LC_CTYPE=Japanese_Japan.932 LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C [5] LC_TIME=Japanese_Japan.932 attached base packages: [1] stats graphics grDevices utils datasets methods base loaded via a namespace (and not attached): [1] compiler_4.0.2 tools_4.0.2 yaml_2.2.1 >
データ読み込み
データは MASS
パッケージに同梱されている Cars93
データの一部を用います。
> library(tidyverse) > library(jsonlite) 次のパッケージを付け加えます: ‘jsonlite’ 以下のオブジェクトは ‘package:purrr’ からマスクされています: flatten > > car_data <- MASS::Cars93 %>% + as_tibble %>% + select(1:5) > car_data # A tibble: 93 x 5 Manufacturer Model Type Min.Price Price <fct> <fct> <fct> <dbl> <dbl> 1 Acura Integra Small 12.9 15.9 2 Acura Legend Midsize 29.2 33.9 3 Audi 90 Compact 25.9 29.1 4 Audi 100 Midsize 30.8 37.7 5 BMW 535i Midsize 23.7 30 6 Buick Century Midsize 14.2 15.7 7 Buick LeSabre Large 19.9 20.8 8 Buick Roadmaster Large 22.6 23.7 9 Buick Riviera Midsize 26.3 26.3 10 Cadillac DeVille Large 33 34.7 # ... with 83 more rows
tibbleそのまま出力
素直に toJSON()
すると、一つの行の各要素が同じ階層内に格納された形で出力されます。
> car_data %>% + toJSON(pretty = TRUE) [ { "Manufacturer": "Acura", "Model": "Integra", "Type": "Small", "Min.Price": 12.9, "Price": 15.9 }, { "Manufacturer": "Acura", "Model": "Legend", "Type": "Midsize", "Min.Price": 29.2, "Price": 33.9 }, ...
1段ネストされたjsonを出力
ネストされたjsonを出力するためには、一度何らかの変数のセットで他の変数をネストしてから toJSON()
します。
例えば、 Manufacturer
で他の変数をネストしてみます。
> car_data %>% + group_by(Manufacturer) %>% + nest() %>% + toJSON(pretty = TRUE) [ { "Manufacturer": "Acura", "data": [ { "Model": "Integra", "Type": "Small", "Min.Price": 12.9, "Price": 15.9 }, { "Model": "Legend", "Type": "Midsize", "Min.Price": 29.2, "Price": 33.9 } ] }, { "Manufacturer": "Audi", "data": [ { "Model": "90", "Type": "Compact", "Min.Price": 25.9, "Price": 29.1 }, { "Model": "100", "Type": "Midsize", "Min.Price": 30.8, "Price": 37.7 } ] }, ...
Manufacturer
と Type
の2変数でネストすると、
> car_data %>% + group_by(Manufacturer,Type) %>% + nest() %>% + toJSON(pretty = TRUE) [ { "Manufacturer": "Acura", "Type": "Small", "data": [ { "Model": "Integra", "Min.Price": 12.9, "Price": 15.9 } ] }, { "Manufacturer": "Acura", "Type": "Midsize", "data": [ { "Model": "Legend", "Min.Price": 29.2, "Price": 33.9 } ] },
2段ネストされたjsonを出力
次は、ネストされたjsonの中で更にネストされたjsonを出力します。
この場合は, purrr:map()
を使うのが便利です。
例えば、Manufacturer
の内部で Type
によって更にネストしてみます。
> car_data %>% + group_by(Manufacturer) %>% + nest() %>% + mutate(data = map(data,group_by,Type) %>% + map(nest)) %>% + toJSON(pretty = TRUE) [ { "Manufacturer": "Acura", "data": [ { "Type": "Small", "data": [ { "Model": "Integra", "Min.Price": 12.9, "Price": 15.9 } ] }, { "Type": "Midsize", "data": [ { "Model": "Legend", "Min.Price": 29.2, "Price": 33.9 } ] } ] }, { "Manufacturer": "Audi", "data": [ { "Type": "Compact", "data": [ { "Model": "90", "Min.Price": 25.9, "Price": 29.1 } ] }, { "Type": "Midsize", "data": [ { "Model": "100", "Min.Price": 30.8, "Price": 37.7 } ] } ] }, ...
Enjoy!