0Pricing
R Academy · บทเรียน

การจัดการโครงสร้าง JSON แบบซ้อนกัน

คลี่ JSON ที่ซ้อนกันหลายระดับให้เป็นกรอบข้อมูลแบบเป็นระเบียบเพื่อการวิเคราะห์

การจัดการโครงสร้าง JSON แบบซ้อนกัน เป็นบทเรียน R Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน R Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใด JSON ที่ซ้อนกันจึงจัดการได้ยาก

REST API มักส่งคืน JSON ที่ซ้อนกันหลายชั้น โดยฟิลด์เดียวอาจมีอาร์เรย์ของออบเจ็กต์ ซึ่งภายในก็มีออบเจ็กต์เพิ่มเติมอีก การคลี่โครงสร้างนี้ให้เป็นกรอบข้อมูลที่เป็นระเบียบจำเป็นต้องเข้าใจการทำงานร่วมกันของ jsonlite, purrr และ tidyr

# 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() — การแยกวิเคราะห์พื้นฐาน

jsonlite::fromJSON() จะแปลงสตริง JSON หรือเส้นทางไฟล์เป็นออบเจ็กต์ R JSON แบบแบนอย่างง่ายจะกลายเป็นลิสต์หรือกรอบข้อมูล ส่วน JSON ที่ซ้อนกันจะกลายเป็นลิสต์ซ้อนกัน โดยอาร์เรย์ของออบเจ็กต์จะกลายเป็นกรอบข้อมูลที่เก็บอยู่ภายในคอลัมน์ลิสต์

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() พร้อม flatten = TRUE

อาร์กิวเมนต์ flatten = TRUE จะสั่งให้ fromJSON() คลี่กรอบข้อมูลที่ซ้อนกันออกเป็นคอลัมน์แบบเรียกซ้ำ โดยใช้ชื่อที่คั่นด้วยจุด วิธีนี้ทำงานได้ดีกับการซ้อนกันหนึ่งระดับ และเป็นวิธีที่รวดเร็วที่สุดสำหรับจัดการ JSON ที่ซ้อนกันในระดับปานกลาง

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)

อาร์เรย์ที่ซ้อนกันจะกลายเป็นคอลัมน์ลิสต์

เมื่อฟิลด์ JSON มีอาร์เรย์ของออบเจ็กต์ fromJSON() จะเก็บฟิลด์นั้นเป็นคอลัมน์ลิสต์ในกรอบข้อมูล โดยแต่ละเซลล์จะเก็บกรอบข้อมูลหนึ่งกรอบ คุณต้องเข้าถึงหรือคลี่ข้อมูลเหล่านี้อย่างชัดเจน

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() — ดึงฟิลด์ที่ซ้อนกัน

purrr::map() จะใช้ฟังก์ชันกับแต่ละองค์ประกอบของลิสต์ เมื่อแต่ละองค์ประกอบเป็นลิสต์ที่มีชื่อ (ออบเจ็กต์ JSON ที่แยกวิเคราะห์แล้ว) คุณสามารถส่งสตริงเพื่อดึงฟิลด์ที่มีชื่อเดียวกันจากทุกองค์ประกอบได้ ซึ่งเป็นทางเลือกแทนลูปที่กระชับ

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() พร้อมทางลัดแบบสตริง

purrr::map(list, 'field_name') เป็นรูปแบบย่อสำหรับดึงฟิลด์ที่มีชื่อจากทุกองค์ประกอบ เทียบเท่ากับ map(list, function(x) x[['field_name']]) ใช้ map_chr(), map_dbl() และอื่น ๆ เพื่อให้ได้เวกเตอร์อะตอมที่มีชนิดแน่นอนแทนลิสต์

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)

การซ้อนหลายชั้นด้วยสายโซ่ map()

สำหรับ JSON ที่ซ้อนกันลึกหลายชั้น ให้เรียกใช้ map() หลายครั้งต่อกัน แต่ละการเรียกจะเลื่อนลงไปหนึ่งระดับ ใช้ map(list, 'field') ในแต่ละระดับ และใช้ map_*() ที่ระบุชนิดในขั้นตอนระดับในสุดเพื่อดึงค่าท้ายสุด

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() — คลี่คอลัมน์ลิสต์

tidyr::unnest() จะขยายคอลัมน์ลิสต์ที่มีกรอบข้อมูล โดยสร้างหนึ่งแถวต่อหนึ่งองค์ประกอบที่ซ้อนกัน นี่เป็นแนวทางมาตรฐานของ tidy สำหรับคลี่ความสัมพันธ์แบบหนึ่งต่อหลายจากข้อมูล JSON

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() กับกรอบข้อมูล

jsonlite::flatten() ทำงานกับกรอบข้อมูลที่แยกวิเคราะห์แล้ว (ไม่ใช่สตริง JSON) โดยจะขยายคอลัมน์กรอบข้อมูลที่ซ้อนกันทั้งหมดแบบเรียกซ้ำเป็นคอลัมน์ชื่อที่คั่นด้วยจุด ฟังก์ชันนี้มีประโยชน์หลังใช้ fromJSON(..., flatten = FALSE) เมื่อคุณต้องการคลี่ข้อมูลในขั้นตอนหลังการประมวลผล

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 ใน JSON ที่ซ้อนกัน

ค่า null ใน JSON จะถูกแยกวิเคราะห์เป็น NULL ใน R ซึ่งก่อปัญหาเมื่อสร้างกรอบข้อมูล เพราะ NULL ในลิสต์จะทำให้องค์ประกอบนั้นหายไปทั้งหมด ใช้ purrr::map() พร้อมอาร์กิวเมนต์ .default หรือ %||% เพื่อแทนค่าที่หายไปอย่างปลอดภัย

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

กระบวนการสมบูรณ์: จาก API JSON สู่กรอบข้อมูลที่เป็นระเบียบ

รวมทุกอย่างเข้าด้วยกัน: กระบวนการที่สมจริงสำหรับแยกวิเคราะห์ JSON ที่ซ้อนกันจาก API ดึงฟิลด์ด้วย purrr จัดการค่า Null และสร้างกรอบข้อมูลที่เป็นระเบียบพร้อมสำหรับการวิเคราะห์

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)

ตรวจสอบความเข้าใจอย่างรวดเร็ว

คุณมีกรอบข้อมูล df ซึ่งคอลัมน์ orders เป็นคอลัมน์ลิสต์ที่มีกรอบข้อมูล (หนึ่งกรอบต่อผู้ใช้หนึ่งคน) ฟังก์ชันใดจะขยายข้อมูลนี้ให้เป็นหนึ่งแถวต่อหนึ่งคำสั่งซื้อ

ประเด็นสำคัญของ JSON แบบซ้อนกัน

การจัดการ JSON แบบซ้อนกันใน R ต้องใช้ชุดเครื่องมือหลายระดับ:

  • fromJSON(json, flatten = TRUE) — คลี่โครงสร้างที่ซ้อนกันออกอัตโนมัติหนึ่งระดับ
  • fromJSON(json, simplifyDataFrame = FALSE) — รับรายการของรายการเพื่อประมวลผลด้วยตนเอง
  • อาร์เรย์ที่ซ้อนกัน → คอลัมน์รายการในกรอบข้อมูลผลลัพธ์
  • purrr::map_chr/dbl/int(list, 'field') — ดึงค่าตามชนิดข้อมูลจากทุกองค์ประกอบ
  • การเรียก map() ต่อกันจะไล่ลงไปตามระดับของโครงสร้างที่ซ้อนกันลึก
  • tidyr::unnest(df, cols = col) — ขยายคอลัมน์รายการที่เป็นกรอบข้อมูล
  • jsonlite::flatten(df) — คลี่คอลัมน์กรอบข้อมูลที่ซ้อนกันหลังการแยกวิเคราะห์
  • ตรวจสอบ NULL ให้รัดกุมเสมอด้วย if (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)

คำถามที่พบบ่อย

บทเรียน “การจัดการโครงสร้าง JSON แบบซ้อนกัน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจัดการโครงสร้าง JSON แบบซ้อนกัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส R Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจัดการโครงสร้าง JSON แบบซ้อนกัน”

คลี่ JSON ที่ซ้อนกันหลายระดับให้เป็นกรอบข้อมูลแบบเป็นระเบียบเพื่อการวิเคราะห์ คุณปฏิบัติ R Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน R Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน R Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การจัดการโครงสร้าง JSON แบบซ้อนกัน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน R Academy นี้ได้ไหม

ได้ บทเรียน R Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การแยกวิเคราะห์ JSON ด้วย jsonlite
  2. การส่งคำขอ HTTP ด้วย httr2
  3. การเรียกใช้ REST API ใน R
  4. การจัดการโครงสร้าง JSON แบบซ้อนกัน
← กลับไปที่ R Academy