Sisäkkäisten JSON-rakenteiden käsittely
Muuntakaa syvästi sisäkkäinen JSON analyysia varten selkeärakenteisiksi data frameiksi.
Sisäkkäisten JSON-rakenteiden käsittely on ilmainen R Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu R Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. R Academy-kurssilla on yhteensä 4 oppituntia.
Miksi sisäkkäinen JSON on hankalaa
REST API -rajapinnat palauttavat usein syvästi sisäkkäistä JSON-dataa, jossa yksi kenttä voi sisältää objektien taulukon, joka puolestaan sisältää lisää objekteja. Tämän rakenteen litistäminen tidy-muotoiseksi data frameksi edellyttää, että ymmärrätte, miten jsonlite, purrr ja tidyr toimivat yhdessä.
# Example nested JSON from a REST API:
json_str <- '{
"user": {
"id": 1,
"name": "Alice",
"orders": [
{"order_id": 101, "total": 59.99, "status": "shipped"},
{"order_id": 102, "total": 24.50, "status": "pending"}
]
}
}'
# The challenge: 'orders' is an array of objects inside 'user'
cat('Nested JSON loaded as string, length:', nchar(json_str))fromJSON() — perusteet
jsonlite::fromJSON() muuntaa JSON-merkkijonon tai tiedostopolun R-objekteiksi. Yksinkertaisesta litteästä JSON-datasta tulee lista tai data frame. Sisäkkäisestä JSON-datasta tulee sisäkkäinen lista — objektien taulukoista muodostuu data frameja, jotka tallennetaan listasarakeisiin.
library(jsonlite)
# Parse flat JSON
flat_json <- '{"name": "Alice", "age": 30, "score": 95.5}'
result <- fromJSON(flat_json)
cat('Name:', result$name, '\n')
cat('Age: ', result$age, '\n')
# Parse an array of objects — becomes a data frame
array_json <- '[{"id":1,"val":10},{"id":2,"val":20},{"id":3,"val":30}]'
df <- fromJSON(array_json)
cat('Class:', class(df), '\n')
print(df)fromJSON() ja flatten = TRUE
Argumentti flatten = TRUE käskee fromJSON()-funktiota purkamaan sisäkkäiset data framet rekursiivisesti sarakkeiksi, joiden nimet erotellaan pisteillä. Tämä toimii hyvin yhdellä sisäkkäisyyden tasolla ja on nopein tapa käsitellä kohtalaisen sisäkkäistä JSON-dataa.
library(jsonlite)
json_str <- '[{
"id": 1,
"name": "Alice",
"address": {"city": "Berlin", "country": "Germany"}
},{
"id": 2,
"name": "Bob",
"address": {"city": "Paris", "country": "France"}
}]'
# Without flatten:
nested_df <- fromJSON(json_str, flatten = FALSE)
cat('address class:', class(nested_df$address), '\n')
# With flatten = TRUE:
flat_df <- fromJSON(json_str, flatten = TRUE)
cat('Columns:', names(flat_df), '\n')
print(flat_df)Sisäkkäisistä taulukoista tulee listasarakkeita
Kun JSON-kenttä sisältää objektien taulukon, fromJSON() tallentaa sen data framen listasarakkeeksi — jokainen solu sisältää data framen. Nämä on käsiteltävä tai purettava erikseen.
library(jsonlite)
json_str <- '[{
"user_id": 1,
"tags": ["R", "Python", "SQL"]
},{
"user_id": 2,
"tags": ["Java", "Kotlin"]
}]'
df <- fromJSON(json_str)
cat('tags column class:', class(df$tags), '\n')
# Access tags for user 1:
cat('User 1 tags:', df$tags[[1]], '\n')
cat('User 2 tags:', df$tags[[2]])purrr::map() — sisäkkäisten kenttien poimiminen
purrr::map() käyttää funktiota listan jokaiseen alkioon. Kun kukin alkio on nimetty lista (jäsennetty JSON-objekti), voitte antaa merkkijonon poimimaan nimetyn kentän jokaisesta alkiosta — tämä korvaa silmukan tiiviillä tavalla.
library(jsonlite)
library(purrr)
json_str <- '[{
"id": 1,
"meta": {"score": 88, "grade": "B"}
},{
"id": 2,
"meta": {"score": 95, "grade": "A"}
},{
"id": 3,
"meta": {"score": 72, "grade": "C"}
}]'
records <- fromJSON(json_str, simplifyDataFrame = FALSE)
# Extract 'score' from each record's 'meta' object
scores <- map_dbl(records, function(r) r$meta$score)
grades <- map_chr(records, function(r) r$meta$grade)
cat('Scores:', scores, '\n')
cat('Grades:', grades)purrr::map() ja merkkijonolyhenne
purrr::map(list, 'field_name') on lyhyt muoto nimetyn kentän poimimiseen jokaisesta alkiosta — vastaa komentoa map(list, function(x) x[['field_name']]). Käyttäkää map_chr()-, map_dbl()- ja muita vastaavia funktioita saadaksenne listojen sijaan tyypitettyjä atomivektoreita.
library(jsonlite)
library(purrr)
json_str <- '[{"name":"Alice","score":90},{"name":"Bob","score":78},{"name":"Carol","score":85}]'
# Parse as list of lists
records <- fromJSON(json_str, simplifyDataFrame = FALSE)
# String shortcut to extract field
names_vec <- map_chr(records, 'name')
scores_vec <- map_dbl(records, 'score')
cat('Names: ', names_vec, '\n')
cat('Scores:', scores_vec, '\n')
# Build a clean data frame
clean_df <- data.frame(name = names_vec, score = scores_vec)
print(clean_df)Syvä sisäkkäisyys map()-ketjuilla
Syvästi sisäkkäistä JSON-dataa käsiteltäessä ketjuttakaa useita map()-kutsuja. Jokainen kutsu siirtyy yhden tason alemmas. Käyttäkää kullakin tasolla komentoa map(list, 'field') ja poimikaa lopullinen arvo sisimmällä tasolla tyypitetyllä map_*()-funktiolla.
library(jsonlite)
library(purrr)
json_str <- '[{
"id": 1,
"company": {"hq": {"city": "Berlin", "country": "Germany"}}
},{
"id": 2,
"company": {"hq": {"city": "Tokyo", "country": "Japan"}}
}]'
records <- fromJSON(json_str, simplifyDataFrame = FALSE)
# Navigate: records -> company -> hq -> city
cities <- map_chr(records, function(r) r$company$hq$city)
cat('Cities:', cities, '\n')
# Or using nested map shortcut:
ids <- map_int(records, 'id')
cat('IDs:', ids)tidyr::unnest() — listasarakkeiden litistäminen
tidyr::unnest() laajentaa data frameja sisältävän listasarakkeen ja luo yhden rivin jokaista sisäkkäistä alkiota kohden. Tämä on tidy-mallin mukainen vakiotapa JSON-datan yksi-moneen-suhteiden litistämiseen.
library(jsonlite)
library(tidyr)
library(dplyr)
json_str <- '[{
"user_id": 1,
"orders": [{"oid":101,"total":50},{"oid":102,"total":30}]
},{
"user_id": 2,
"orders": [{"oid":103,"total":80}]
}]'
df <- fromJSON(json_str)
cat('Before unnest, rows:', nrow(df), '\n')
cat('orders class:', class(df$orders), '\n')
# Unnest expands one row per order
expanded <- unnest(df, cols = orders)
cat('After unnest, rows:', nrow(expanded), '\n')
print(expanded)jsonlite::flatten() data frameille
jsonlite::flatten() toimii valmiiksi jäsennellylle data framelle (ei JSON-merkkijonolle) ja laajentaa rekursiivisesti kaikki sisäkkäisiä data frameja sisältävät sarakkeet pisteillä erotelluiksi nimisarakeiksi. Se on hyödyllinen fromJSON(..., flatten = FALSE)-kutsun jälkeen, kun haluatte tehdä litistyksen jälkikäsittelyvaiheena.
library(jsonlite)
json_str <- '[{
"id": 1,
"profile": {"age": 25, "city": "Rome"}
},{
"id": 2,
"profile": {"age": 31, "city": "Oslo"}
}]'
# Parse without auto-flatten
nested <- fromJSON(json_str, flatten = FALSE)
cat('Columns before flatten:', names(nested), '\n')
cat('profile class:', class(nested$profile), '\n')
# Apply flatten() post-hoc
flat <- flatten(nested)
cat('Columns after flatten:', names(flat), '\n')
print(flat)Null-arvojen käsittely sisäkkäisessä JSON-datassa
JSON:n null-arvot jäsentyvät R:ssä arvoksi NULL, mikä aiheuttaa ongelmia data frameja rakennettaessa — listassa oleva NULL poistaa alkion kokonaan. Käyttäkää purrr::map()-funktiota argumentin .default kanssa tai operaattoria %||% puuttuvien arvojen turvalliseen korvaamiseen.
library(jsonlite)
library(purrr)
json_str <- '[{"id":1,"email":"alice@example.com"},{"id":2,"email":null},{"id":3,"email":"carol@example.com"}]'
records <- fromJSON(json_str, simplifyDataFrame = FALSE)
# Unsafe: NULL drops the element
# emails <- map_chr(records, 'email') # ERROR on null
# Safe: provide a default for missing values
emails <- map_chr(records, function(r) {
if (is.null(r$email)) NA_character_ else r$email
})
cat('Emails:', emails)
cat('NAs:', sum(is.na(emails)))Koko työnkulku: API:n JSON-datasta tidy-muotoiseksi data frameksi
Kootaan kaikki yhteen: realistinen työnkulku, joka jäsentää API-rajapinnasta saadun sisäkkäisen JSON-datan, poimii kentät purrr-paketilla, käsittelee null-arvot ja tuottaa analyysiin valmiin tidy-muotoisen data framen.
library(jsonlite)
library(purrr)
library(dplyr)
# Simulated API response
api_json <- '[{
"id": 1, "name": "Alice",
"stats": {"score": 92, "rank": 1}
},{
"id": 2, "name": "Bob",
"stats": null
},{
"id": 3, "name": "Carol",
"stats": {"score": 85, "rank": 3}
}]'
records <- fromJSON(api_json, simplifyDataFrame = FALSE)
result <- tibble(
id = map_int(records, 'id'),
name = map_chr(records, 'name'),
score = map_dbl(records, function(r) if (is.null(r$stats)) NA_real_ else r$stats$score),
rank = map_int(records, function(r) if (is.null(r$stats)) NA_integer_ else r$stats$rank)
)
print(result)Pikatesti
Teillä on data frame df, jonka sarake orders on listasarakkeena ja sisältää data frameja (yhden käyttäjää kohden). Millä funktiolla tästä saadaan yksi rivi jokaista tilausta kohden?
Sisäkkäinen JSON – tärkeimmät opit
Sisäkkäisen JSON-datan käsittely R:ssä edellyttää kerroksittaista työkalupakkia:
fromJSON(json, flatten = TRUE)— litistää sisäkkäisyyttä automaattisesti yhden tason verranfromJSON(json, simplifyDataFrame = FALSE)— palauttaa listojen listan manuaalista käsittelyä varten- Sisäkkäiset taulukot → tuloksena syntyvän data framen list-sarakkeita
purrr::map_chr/dbl/int(list, 'field')— poimii tyypitetyt arvot jokaisesta alkiosta- Ketjutetut
map()-kutsut etenevät syvän sisäkkäisyyden tasolta toiselle tidyr::unnest(df, cols = col)— laajentaa data frameja sisältävät list-sarakkeetjsonlite::flatten(df)— litistää sisäkkäiset data frame -sarakkeet jäsentämisen jälkeen- Varaudu aina
NULL-arvoon rakenteellaif (is.null(x)) NA else x
library(jsonlite)
library(purrr)
# Quick reference:
json <- '[{"id":1,"info":{"val":10}},{"id":2,"info":null}]'
recs <- fromJSON(json, simplifyDataFrame = FALSE)
# Safe extraction with null guard
vals <- map_dbl(recs, function(r) {
if (is.null(r$info)) NA_real_ else r$info$val
})
result <- data.frame(id = map_int(recs, 'id'), val = vals)
print(result)Opi R tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 43
- Oppitunnit
- 159
Usein kysytyt kysymykset
Onko oppitunti ”Sisäkkäisten JSON-rakenteiden käsittely” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa R Academy-oppimispolun 3 oppituntia, myös oppitunnin “Sisäkkäisten JSON-rakenteiden käsittely”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. R Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Sisäkkäisten JSON-rakenteiden käsittely”?
Muuntakaa syvästi sisäkkäinen JSON analyysia varten selkeärakenteisiksi data frameiksi. Harjoittelet R Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni R Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin R Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Sisäkkäisten JSON-rakenteiden käsittely”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä R Academy-oppitunnilla?
Kyllä. Jokainen R Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- JSON-jäsentäminen jsonlite-paketilla
- HTTP-pyyntöjen tekeminen httr2-paketilla
- REST-rajapintojen käyttäminen R:ssä
- Sisäkkäisten JSON-rakenteiden käsittely