R: بيانات JSON و XML: دليل شامل لـ jsonlite

آخر تحديث: 2026-08-26

في الدرس السابق، تعرفنا على CSV وExcel — ولكن في عصر الويب، أصبحت البيانات تُستخدم بشكل متزايد بتنسيق JSON (استجابات واجهات برمجة التطبيقات، وملفات التكوين، وقواعد بيانات NoSQL). في هذا الدرس، سنتعرف على الطرق القياسية لقراءة وكتابة JSON في R: jsonlite، بالإضافة إلى كيفية التعامل مع بيانات XML: xml2.

بعد الانتهاء من هذا الدرس، ستتمكن من تحويل بيانات JSON المتداخلة التي تُرجعها واجهة برمجة التطبيقات (API) إلى إطار بيانات في غضون 5 ثوانٍ، وكذلك كتابة ملفات التكوين الخاصة بك بلغة JSON.

1. ما ستتعلمه



2. قصة مجموعة بيانات واجهة برمجة التطبيقات (API)

(1) المشكلة: تعرض واجهة برمجة التطبيقات (API) بيانات JSON متداخلة

يعمل بوب على تطوير تطبيق للطقس ويحتاج إلى استرداد البيانات من واجهة برمجة تطبيقات (API) خاصة بالطقس:

JSON
{
  "status": "ok",
  "data": {
    "city": "Beijing",
    "date": "2024-01-15",
    "forecast": [
      {"day": "Monday", "high": 5, "low": -3, "weather": "Sunny"},
      {"day": "Tuesday", "high": 7, "low": -1, "weather": "Cloudy"},
      {"day": "Wednesday", "high": 3, "low": -5, "weather": "Snowy"}
    ]
  }
}

أراد استخراج «توقعات الطقس لـ 7 أيام» وحفظها في لغة R لتحليلها. في لغة Python، استغرق الأمر 10 أسطر من التعليمات البرمجية requests + json؛ أما في لغة R، فقد تم ذلك في سطر واحد—

(2) الحل باستخدام لغة R

R
library(jsonlite)

# 1. Reading nested data with a single line of code JSON
weather <- fromJSON("https://api.weather.com/forecast?city=Beijing")

# 2. Extract 7 Weather Forecast(Nested → Data Frame)
forecast <- weather$data$forecast  # It's a data frame!

# 3. Write JSON Layout
config <- list(api_key = "xxx", cities = c("Beijing", "Shanghai"))
write_json(config, "config.json", pretty = TRUE)

JSON متداخل في 3 أسطر فقط من الكود. هذه هي «السحر» الذي يتميز به jsonlite.

100%
graph LR
    A[API URL<br/>weather.com/forecast] --> B[jsonlite::fromJSON]
    B --> C{Nested JSON}
    C --> D[forecast Array<br/>Auto-rotate data.frame]
    C --> E[current Object<br/>Auto-rotate list]
    D --> F[dplyr Analysis<br/>7 Weather Forecast]
    D --> G[ggplot2 Drawing<br/>Trend Visualization]
    E --> H[Real-time Weather Data]

    style A fill:#cce5ff
    style B fill:#d4edda
    style C fill:#fff3cd
    style D fill:#f8d7da
    style E fill:#e1d4ff
    style F fill:#ffe1d4
    style G fill:#cce5ff
    style H fill:#d4edda

3. JSON مقابل XML: متى يستخدم أي منهما؟

100%
graph TB
    subgraph JSON[JSON Faction]
        J1[Grammar: Key-value pairs Concise]
        J2[Type: Numbers/String/Boolean/Array/Object]
        J3[Analysis: Fast C Language Implementation]
        J4[R Package: jsonlite]
    end

    subgraph XML[XML Faction]
        X1[Grammar: Nested Tags Long-winded]
        X2[Type: All strings]
        X3[Analysis: slower]
        X4[R Package: xml2]
    end

    JSON --> J5[Web API / NoSQL / Profile]
    XML --> X5[Legacy Enterprise Systems / SOAP / RSS / SVG]

    style JSON fill:#d4edda
    style XML fill:#f8d7da

(1) مقارنة بين الصيغتين

الخاصية JSON XML
الاسم الكامل ترميز كائنات جافا سكريبت لغة الترميز القابلة للتوسيع
بناء الجملة {"key": "value"} <key>value</key>
سهولة القراءة الإيجاز الإسهاب
نوع البيانات عدد، سلسلة، منطقية، فارغة، مصفوفة، كائن جميع السلاسل
سرعة التحليل سريعة أبطأ
حالات الاستخدام الرئيسية واجهات برمجة التطبيقات على الويب، NoSQL، ملفات التكوين الأنظمة المؤسسية القديمة، SOAP، المستندات (RSS، SVG)
حزمة R jsonlite xml2

(2) مثال على JSON

JSON
{
  "name": "Alice",
  "age": 25,
  "is_student": true,
  "scores": [85, 90, 92],
  "address": {
    "city": "Beijing",
    "zip": "100000"
  }
}

(3) مثال على XML

XML
<student>
  <name>Alice</name>
  <age>25</age>
  <scores>
    <item>85</item>
    <item>90</item>
    <item>92</item>
  </scores>
  <address>
    <city>Beijing</city>
    <zip>100000</zip>
  </address>
</student>
💡 نصيحة: تستخدم جميع المشاريع الجديدة تقريبًا لغة JSON — فهي موجزة وسهلة القراءة ويتم تحليلها بسرعة. ولا تزال لغة XML تُستخدم فقط في الأنظمة المؤسسية القديمة والبيانات الحكومية.



4. الوظائف الأساسية الأربع لـ jsonlite

(1) جدول مرجعي سريع للوظائف

الوظيفة الغرض
fromJSON() JSON → كائن R (قائمة / إطار بيانات)
toJSON() كائن R → سلسلة JSON
read_json() قراءة ملفات JSON/عناوين URL
write_json() كتابة ملف JSON

(2) شرح مفصل لـ fromJSON

R
library(jsonlite)

# 1. Read JSON String
json_str <- '{"name": "Alice", "age": 25}'
fromJSON(json_str)
# $name
# [1] "Alice"
# 
# $age
# [1] 25

# 2. Read JSON Documents
df <- fromJSON("data.json")

# 3. Read URL(API)
weather <- fromJSON("https://api.example.com/weather?city=beijing")

# 4. Expand directly into a data frame
json_array <- '[{"name": "A", "age": 20}, {"name": "B", "age": 25}]'
fromJSON(json_array)
#   name age
# 1    A  20
# 2    B  25  ← Automatically Rotate Data Frames!

(3) التسوية التلقائية لبيانات JSON المتداخلة

R
nested <- '{
  "status": "ok",
  "data": {
    "city": "Beijing",
    "forecast": [
      {"day": "Monday", "high": 5, "low": -3},
      {"day": "Tuesday", "high": 7, "low": -1}
    ]
  }
}'

result <- fromJSON(nested)
str(result)
# List of 2
#  $ status: chr "ok"
#  $ data  : List of 2
#   ..$ city     : chr "Beijing"
#   ..$ forecast :'data.frame':	2 obs. of  3 variables:
#   .. ..$ day  : chr [1:2] "Monday" "Tuesday"
#   .. ..$ high: num [1:2] 5 7
#   .. ..$ low : num [1:2] -3 -1

# Automatically Convert Nested Arrays to DataFrames!
result$data$forecast
#   day high low
# 1 Monday    5  -3
# 2 Tuesday    7  -1
💡 نصيحة: تكمن روعة jsonlite في قدرتها على تحويل المصفوفات المتداخلة تلقائيًا إلى إطارات بيانات — أما في لغات البرمجة الأخرى (مثل بايثون)، فيتعين عليك القيام بذلك يدويًّا.



5. شرح مفصل لوظيفة toJSON

(1) قواعد النحو الأساسية

R
toJSON(x, pretty = FALSE, auto_unbox = FALSE, dataframe = "columns")

(2) التطبيق العملي

R
# 1. Data Frame → JSON
df <- data.frame(name = c("A", "B"), age = c(20, 25))
toJSON(df)
# [{"name":"A","age":20},{"name":"B","age":25}]

# 2. Format the output(Indented)
toJSON(df, pretty = TRUE)
# [
#   {
#     "name": "A",
#     "age": 20
#   },
#   {
#     "name": "B",
#     "age": 25
#   }
# ]

# 3. List → JSON
config <- list(
  api_key = "secret123",
  cities = c("Beijing", "Shanghai", "Guangzhou"),
  options = list(timeout = 30, retry = 3)
)
toJSON(config, pretty = TRUE)
# {
#   "api_key": "secret123",
#   "cities": ["Beijing", "Shanghai", "Guangzhou"],
#   "options": {
#     "timeout": 30,
#     "retry": 3
#   }
# }

(3) المعلمات الرئيسية

المعلمة الوظيفة القيمة الافتراضية
pretty التنسيق (مع المسافة البادئة) FALSE
auto_unbox إزالة المصفوفة تلقائيًا من المتجهات ذات الطول 1 FALSE
dataframe وضع عرض إطار البيانات "أعمدة"
R
# auto_unbox:Prevent a single value from becoming an array
toJSON(list(name = "Alice", scores = c(85)))  # Default
# {"name":["Alice"],"scores":[85]}

toJSON(list(name = "Alice", scores = c(85)), auto_unbox = TRUE)
# {"name":"Alice","scores":85}  ← Do not convert single values to arrays

(4) write_json: الكتابة إلى ملف

R
# Write JSON Document
write_json(config, "config.json", pretty = TRUE)

# Write concisely JSON(No indentation)
write_json(data, "data.json")

# Append to the file(Read first, Merge, then Write)
old <- read_json("data.json", simplifyVector = FALSE)
new <- c(old, list(updated_at = Sys.time()))
write_json(new, "data.json", pretty = TRUE)


6. تدريب عملي: استخراج بيانات واجهة برمجة التطبيقات (API) دفعة واحدة

(1) استدعاءات واجهة برمجة التطبيقات (API) الفعلية

R
library(jsonlite)
library(dplyr)

# Call a public API(GitHub User Information)
user_info <- fromJSON("https://api.github.com/users/hadley")
str(user_info)
# List of 50+
#  $ login              : chr "hadley"
#  $ id                 : int 4192
#  $ name               : chr "Hadley Wickham"
#  $ company            : chr "@posit-pbc"
#  $ location           : chr "Houston, TX"
#  $ public_repos       : int 50
#  ...

# Extract Key Fields
info <- tibble(
  name = user_info$name,
  company = user_info$company,
  repos = user_info$public_repos,
  followers = user_info$followers
)
print(info)

(2) التقاط بيانات عدة مستخدمين دفعة واحدة

R
# Retrieve multiple items in bulk GitHub Number of repositories per user
users <- c("hadley", "yihui", "jtleek", "rstudio")

repos_data <- lapply(users, function(user) {
  info <- fromJSON(paste0("https://api.github.com/users/", user))
  tibble(
    user = user,
    repos = info$public_repos,
    followers = info$followers,
    created_at = as.Date(info$created_at)
  )
}) |> bind_rows()

print(repos_data)


7. xml2: قراءة ملفات XML

(1) التثبيت والوظائف الأساسية

R
install.packages("xml2")
library(xml2)

# 4 Core Functions
read_xml()        # Read XML Document
xml_find_all()    # XPath Query Node
xml_text()        # Extract Node Text
xml_attr()        # Retrieve Node Properties

(2) تجربة عملية: قراءة موجزات RSS

R
# 1. Read RSS(XML Format)
rss <- read_xml("https://www.r-bloggers.com/feed")

# 2. Extract All <item> Node
items <- xml_find_all(rss, "//item")
cat("Found", length(items), "Articles\n")

# 3. Extract the title of each article,Link,Date
articles <- tibble(
  title = xml_text(xml_find_all(items, "./title")),
  link = xml_attr(xml_find_all(items, "./link"), "href"),
  pub_date = xml_text(xml_find_all(items, "./pubDate"))
)

print(head(articles, 3))

(3) تدريب عملي: قراءة ملفات SVG (صور XML)

R
# SVG is an XML format
svg <- read_xml("logo.svg")
# Extract All <circle> cx, cy, r attributes
circles <- xml_find_all(svg, "//circle")
data.frame(
  cx = as.numeric(xml_attr(circles, "cx")),
  cy = as.numeric(xml_attr(circles, "cy")),
  r = as.numeric(xml_attr(circles, "r"))
)


8. تدريب عملي: قراءة وكتابة ملفات التكوين بتنسيق JSON

(1) هيكل المشروع

TEXT 📖 للعرض فقط
project/
├── config.json          # Profile
├── R/
│   ├── main.R           # Main Program
│   └── utils.R          # Utility Functions
└── data/
    └── input.json       # Input Data

(2) مثال على ملف config.json

JSON
{
  "api": {
    "key": "your-api-key",
    "endpoint": "https://api.example.com",
    "timeout": 30
  },
  "cities": ["Beijing", "Shanghai", "Guangzhou", "Shenzhen"],
  "options": {
    "log_level": "info",
    "max_retries": 3
  }
}

(3) تحميل إعدادات برنامج R

R
# Load Configuration
config <- read_json("config.json", simplifyVector = FALSE)
print(config$cities)
# [1] "Beijing" "Shanghai" "Guangzhou" "Shenzhen"

# Using the Configuration
for (city in config$cities) {
  url <- paste0(config$api$endpoint, "?city=", city, "&key=", config$api$key)
  data <- fromJSON(url)
  # Processing data...
}

# Update Configuration
config$options$log_level <- "debug"
write_json(config, "config.json", pretty = TRUE, auto_unbox = TRUE)


9. مثال كامل: استخراج البيانات من واجهة برمجة التطبيقات (API) + تخزين البيانات بتنسيق JSON

فيما يلي مثال على مسار عمل كامل يربط بين جميع المفاهيم التي تم تناولها في هذا الدرس.

▶ مثال: استخراج بيانات واجهة برمجة تطبيقات الطقس وحفظها

R 📖 للعرض فقط
# ============================================
# Weather API Data Extraction + Persistence
# Features:Simulated Crawling 4 City Weather,Save as JSON
# ============================================

library(jsonlite)
library(dplyr)

# 1. Simulation API Response(For use in actual projects fromJSON(url))
mock_api_response <- function(city) {
  set.seed(match(city, c("Beijing", "Shanghai", "Guangzhou", "Shenzhen")))
  list(
    status = "ok",
    data = list(
      city = city,
      date = Sys.Date(),
      current = list(
        temp = sample(0:30, 1),
        humidity = sample(40:90, 1),
        weather = sample(c("Sunny", "Cloudy", "Rainy", "Snowy"), 1)
      ),
      forecast = data.frame(
        day = c("Today", "Tomorrow", "The day after tomorrow", "The day after tomorrow"),
        high = sample(5:30, 4),
        low = sample(-5:15, 4),
        weather = sample(c("Sunny", "Cloudy", "Rainy", "Snowy"), 4, replace = TRUE),
        stringsAsFactors = FALSE
      )
    )
  )
}

# 2. Batch Scraping 4 City
cities <- c("Beijing", "Shanghai", "Guangzhou", "Shenzhen")
cat("=== Fetching 4 City Weather ===\n")
all_weather <- lapply(cities, mock_api_response)
names(all_weather) <- cities

# 3. Retrieve All Forecasts(Nested → Data Frame)
all_forecast <- bind_rows(lapply(all_weather, function(w) {
  fc <- w$data$forecast
  fc$city <- w$data$city
  fc
}))

cat("\n=== 4 The Future of Cities 4 Weather Forecast ===\n")
print(all_forecast)

# 4. Get the current weather(Nested → Data Frame)
current_weather <- bind_rows(lapply(all_weather, function(w) {
  cw <- w$data$current
  tibble(
    city = w$data$city,
    temp = cw$temp,
    humidity = cw$humidity,
    weather = cw$weather
  )
}))

cat("\n=== Current Weather ===\n")
print(current_weather)

# 5. Save as JSON
write_json(all_weather, "all_weather.json", pretty = TRUE, auto_unbox = TRUE)
cat("\n=== Saved all_weather.json ===\n")

# 6. Save as a compressed file JSON(Remove Indentation)
write_json(all_weather, "all_weather_compact.json", auto_unbox = TRUE)

# 7. Read back JSON for verification
reloaded <- read_json("all_weather.json", simplifyVector = FALSE)
cat("\n=== Read-Back Verification ===\n")
cat("Number of cities:", length(reloaded), "\n")
cat("Current Temperature in Beijing:", reloaded$Beijing$data$current$temp, "°C\n")

# 8. Write a concise version for a single city JSON Layout
config <- list(
  api_key = "secret-key-xxx",
  default_city = "Beijing",
  update_interval = 3600,
  enabled_cities = cities
)
write_json(config, "config.json", pretty = TRUE, auto_unbox = TRUE)
cat("\n=== The configuration file has been generated config.json ===\n")

# 9. Read the configuration file
loaded_config <- read_json("config.json", simplifyVector = FALSE)
cat("Default City:", loaded_config$default_city, "\n")
cat("Enable City:", paste(loaded_config$enabled_cities, collapse = ", "), "\n")

# 10. Use jsonlite Processing API Error
cat("\n=== Error Handling Examples ===\n")
error_response <- '{"status": "error", "message": "Invalid API key"}'
result <- tryCatch(
  {
    parsed <- fromJSON(error_response)
    if (parsed$status == "error") stop(parsed$message)
    parsed
  },
  error = function(e) {
    cat("API Error:", e$message, "\n")
    NULL
  }
)
77 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

النتائج المتوقعة (مقتطف):

TEXT 📖 للعرض فقط
=== 4 The Future of Cities 4 Weather Forecast ===
   day high low weather city
1 Today    12  -3      Sunny  Beijing
2 Tomorrow    15   0     Cloudy  Beijing
3 The day after tomorrow     8  -5      Snowy  Beijing
...

=== Current Weather ===
# A tibble: 4 × 4
  city   temp humidity weather
  <chr> <int>    <int> <chr>  
1 Beijing     18       65 Sunny     
2 Shanghai     22       78 Cloudy   
3 Guangzhou     28       85 Rainy     
4 Shenzhen     26       72 Cloudy


❓ أسئلة شائعة

س كيف يمكنني تحويل قائمة تم إرجاعها بواسطة fromJSON إلى data.frame؟
ج يتم تحويل المصفوفات المتداخلة تلقائيًا إلى data.frames؛ أما بالنسبة للقوائم العادية، فاستخدم as.data.frame() or dplyr::bind_rows() لإجبار النظام على إجراء التحويل.
س كيف يمكنني تحويل null في JSON إلى R؟
ج nullNA، trueTRUE، falseFALSE؛ المصفوفات → القوائم/إطارات البيانات. يتولى jsonlite هذه العملية تلقائيًا.

📖 ملخص


📝 تمارين

  1. المشكلة الأساسية: قم بإنشاء سلسلة JSON متداخلة (تحتوي على المصفوفات name وage وscores)، وقم بتحليلها باستخدام fromJSON()، ثم استخدم toJSON(pretty = TRUE) لإخراج نسخة منسقة، مع التحقق من أن البيانات المتداخلة قد تم تسويتها بشكل صحيح.

  2. تمرين أساسي: قم بتحويل إطار بيانات (5 صفوف، 3 أعمدة) إلى صيغة JSON، ثم استخدم read_json() لإعادة قراءته والتحقق من اكتمال البيانات.

  3. المشكلة الأساسية: استخدم xml2 لقراءة سلسلة XML بسيطة، واستخراج سمات name والمحتوى النصي لجميع العقد <item>، وإخراج البيانات في إطار بيانات.

  4. مشكلة متقدمة: قم بمحاكاة استجابة واجهة برمجة التطبيقات (تحتوي على بنية متداخلة من status وdata وforecast)، وقم بتحليلها باستخدام fromJSON، ثم استخدم bind_rows لدمج المصفوفة forecast في إطار بيانات.

  5. التحدي: اكتب برنامجًا كاملاً يقوم بما يلي: ① إنشاء ملف JSON يحتوي على بيانات الطقس لثلاث مدن؛ ② قراءة واستخراج درجة الحرارة الحالية لجميع المدن؛ ③ حساب متوسط درجة الحرارة على المستوى الوطني؛ ④ كتابة النتيجة في ملف جديد باستخدام write_json. التقط لقطة شاشة لإخراج وحدة التحكم واحفظها.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%