1. 引言
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,因其结构清晰、易于阅读和解析,已成为 Web API、配置文件和大数据场景中最常用的数据格式之一。在 R 语言中,处理 JSON 文件是数据科学家和开发者的必备技能。本文将系统介绍 R 语言中 JSON 文件的读取、写入、转换和实战应用,并提供丰富的可运行代码示例。
2. JSON 基础回顾
在深入 R 语言之前,先快速回顾 JSON 的基本语法。JSON 支持以下几种数据类型:
- 对象(Object):由花括号
{}包裹的键值对集合。 - 数组(Array):由方括号
[]包裹的有序值列表。 - 字符串(String):由双引号包裹的文本。
- 数字(Number):整数或浮点数。
- 布尔值(Boolean):
true或false。 - 空值(Null):
null。
下面是一个典型的 JSON 示例:
{
"name": "Alice",
"age": 28,
"is_student": false,
"skills": ["R", "Python", "SQL"],
"address": {
"city": "Beijing",
"zip": "100000"
},
"projects": null
}
3. 常用 JSON 处理包
R 语言中有多个处理 JSON 的包,最常用的包括:
| 包名 | 核心函数 | 特点 |
|---|---|---|
| jsonlite | fromJSON / toJSON | 语法简洁,与 data.frame 无缝衔接,推荐首选 |
| rjson | fromJSON / toJSON | 老牌包,性能一般,维护较少 |
| RJSONIO | fromJSON / toJSON | 基于 R 原生接口,速度较快 |
| jsonify | from_json / to_json | 性能优化,适合大数据量 |
本文以 jsonlite 包为主进行讲解,它是目前 R 社区最流行、文档最完善的 JSON 处理方案。
4. 安装与加载
首先安装并加载 jsonlite 包:
# 安装 jsonlite 包(如果尚未安装)
install.packages("jsonlite")
加载包
library(jsonlite)
5. 读取 JSON 文件
jsonlite 包提供了 fromJSON() 函数,可以从文件、URL 或字符串中读取 JSON 数据。
5.1 从文件读取
假设当前目录下有一个 data.json 文件,内容如下:
{
"name": "Alice",
"age": 28,
"city": "Beijing"
}
使用 fromJSON() 读取:
# 从文件读取 JSON
data <- fromJSON("data.json")
print(data)
输出结果
$name
[1] "Alice"
$age
[1] 28
$city
[1] "Beijing"
5.2 从字符串读取
# 从字符串读取 JSON
json_str <- '{"name": "Bob", "age": 32, "city": "Shanghai"}'
data <- fromJSON(json_str)
print(data$name) # 输出 "Bob"
5.3 从 URL 读取
# 从 API 接口读取 JSON 数据
url <- "https://api.github.com/repos/jeroen/jsonlite"
repo_info <- fromJSON(url)
print(repo_info$full_name)
print(repo_info$stargazers_count)
5.4 读取 JSON 数组为数据框
当 JSON 是数组结构时,fromJSON() 会自动将其转换为 data.frame:
# JSON 数组示例
json_array <- '[{"name": "Alice", "age": 28}, {"name": "Bob", "age": 32}]'
df <- fromJSON(json_array)
print(df)
输出结果
name age
1 Alice 28
2 Bob 32
确认类型
class(df) # [1] "data.frame"
6. 写入 JSON 文件
使用 toJSON() 函数可以将 R 对象转换为 JSON 格式,并通过 write() 或 write_json() 写入文件。
6.1 将数据框写入 JSON
# 创建数据框
df <- data.frame(
name = c("Alice", "Bob", "Charlie"),
age = c(28, 32, 25),
city = c("Beijing", "Shanghai", "Guangzhou"),
stringsAsFactors = FALSE
)
转换为 JSON 字符串
json_data <- toJSON(df, pretty = TRUE)
print(json_data)
写入文件
write(json_data, file = "output.json")
生成的 output.json 文件内容如下:
[
{
"name": "Alice",
"age": 28,
"city": "Beijing"
},
{
"name": "Bob",
"age": 32,
"city": "Shanghai"
},
{
"name": "Charlie",
"age": 25,
"city": "Guangzhou"
}
]
6.2 使用 write_json 快捷函数
# jsonlite 提供 write_json 快捷函数
write_json(df, path = "output2.json", pretty = TRUE)
6.3 将列表写入 JSON
# 创建嵌套列表
my_list <- list(
title = "R JSON Tutorial",
author = list(name = "Alice", email = "alice@example.com"),
tags = c("R", "JSON", "Data Science"),
published = TRUE
)
转换为 JSON 并写入文件
write_json(my_list, path = "list_output.json", pretty = TRUE)
7. JSON 与数据框的相互转换
在实际工作中,最常遇到的需求是在 JSON 和 data.frame 之间进行转换。
7.1 数据框转 JSON
# 数据框转 JSON
df <- data.frame(
id = 1:3,
product = c("Laptop", "Mouse", "Keyboard"),
price = c(5999, 99, 299)
)
默认转换为数组格式
json1 <- toJSON(df)
print(json1)
[{"id":1,"product":"Laptop","price":5999},{"id":2,"product":"Mouse","price":99},{"id":3,"product":"Keyboard","price":299}]
使用 pretty 参数美化输出
json2 <- toJSON(df, pretty = TRUE)
print(json2)
7.2 JSON 转数据框
# JSON 转数据框
json_data <- '[{"id":1,"product":"Laptop","price":5999},{"id":2,"product":"Mouse","price":99}]'
df <- fromJSON(json_data)
print(df)
处理嵌套 JSON
nested_json <- '[
{"name": "Alice", "orders": [{"item": "book", "qty": 2}, {"item": "pen", "qty": 5}]},
{"name": "Bob", "orders": [{"item": "notebook", "qty": 1}]}
]'
df_nested <- fromJSON(nested_json)
print(df_nested)
print(df_nested$orders)
8. 处理嵌套 JSON 数据
真实世界中的 JSON 往往包含嵌套结构,需要特殊处理。
8.1 使用 flatten 参数
# 嵌套 JSON 示例
nested_json <- '{
"user": {
"name": "Alice",
"contact": {
"email": "alice@example.com",
"phone": "13800000000"
}
},
"orders": [
{"id": 101, "amount": 299},
{"id": 102, "amount": 599}
]
}'
默认解析
data <- fromJSON(nested_json)
print(data$user$contact$email) # 输出 "alice@example.com"
使用 flatten 参数展平嵌套结构
data_flat <- fromJSON(nested_json, flatten = TRUE)
print(data_flat)
8.2 处理深层嵌套数组
# 深层嵌套数组
deep_json <- '{
"departments": [
{
"name": "Engineering",
"teams": [
{"name": "Backend", "members": ["Alice", "Bob"]},
{"name": "Frontend", "members": ["Charlie"]}
]
},
{
"name": "Design",
"teams": [
{"name": "UI", "members": ["David"]}
]
}
]
}'
解析嵌套结构
data <- fromJSON(deep_json)
访问嵌套数据
print(data$departments$name)
print(data$departments$teams)
使用 unlist 提取所有成员
all_members <- unlist(data$departments$teams$members)
print(all_members)
9. 实战案例:处理 API 返回数据
下面通过一个完整的实战案例,演示如何从 API 获取 JSON 数据并进行处理。
9.1 获取天气数据
# 使用公开 API 获取天气数据(示例使用 Open-Meteo,无需 API Key)
library(jsonlite)
构造 API 请求 URL
url <- "https://api.open-meteo.com/v1/forecast?latitude=39.9042&longitude=116.4074¤t_weather=true"
获取数据
weather_data <- fromJSON(url)
print(weather_data$current_weather)
提取关键信息
temperature <- weather_data$current_weather$temperature
wind_speed <- weather_data$current_weather$windspeed
print(paste("当前温度:", temperature, "°C"))
print(paste("当前风速:", wind_speed, "km/h"))
9.2 批量处理多个 API 请求
# 批量获取多个城市的天气
cities <- data.frame(
name = c("Beijing", "Shanghai", "Guangzhou"),
lat = c(39.9042, 31.2304, 23.1291),
lon = c(116.4074, 121.4737, 113.2644)
)
循环获取每个城市的天气
results <- lapply(1:nrow(cities), function(i) {
url <- paste0(
"https://api.open-meteo.com/v1/forecast?latitude=",
cities$lat[i],
"&longitude=",
cities$lon[i],
"¤t_weather=true"
)
data <- fromJSON(url)
data.frame(
city = cities$name[i],
temperature = data$current_weather$temperature,
wind_speed = data$current_weather$windspeed
)
})
合并结果
weather_df <- do.call(rbind, results)
print(weather_df)
保存为 JSON 文件
write_json(weather_df, path = "weather_results.json", pretty = TRUE)
10. 性能优化与大数据处理
处理大型 JSON 文件时,需要注意性能和内存管理。
10.1 使用 simplifyVector 参数
# 大数据量 JSON 处理
# 生成模拟数据
set.seed(123)
n <- 10000
df <- data.frame(
id = 1:n,
value = rnorm(n),
category = sample(c("A", "B", "C"), n, replace = TRUE)
)
转换为 JSON
json_data <- toJSON(df)
读取时使用 simplifyVector 加速
df_back <- fromJSON(json_data, simplifyVector = TRUE)
print(dim(df_back)) # [1] 10000 3
10.2 流式处理大文件
# 对于超大文件,可以分块读取
# 使用 jsonlite 的 stream_in 函数(需要 jsonlite 1.5+)
library(jsonlite)
创建示例大文件
big_df <- data.frame(
id = 1:100000,
value = runif(100000)
)
write_json(big_df, path = "big_data.json")
流式读取
con <- file("big_data.json", open = "r")
result <- stream_in(con, pagesize = 10000)
close(con)
print(dim(result))
11. 常见问题与解决方案
在实际使用中,经常会遇到一些 JSON 解析问题,下面列出常见问题及解决方案。
11.1 编码问题
# 处理中文编码问题
# 读取时指定编码
data <- fromJSON("chinese_data.json", encoding = "UTF-8")
写入时确保 UTF-8 编码
write_json(df, path = "output.json", pretty = TRUE, encoding = "UTF-8")
11.2 处理特殊字符
# JSON 中的特殊字符处理
text <- 'He said "Hello" and left'
df <- data.frame(message = text)
转换为 JSON(自动转义特殊字符)
json_data <- toJSON(df)
print(json_data)
[{"message":"He said "Hello" and left"}]
读取回来
df_back <- fromJSON(json_data)
print(df_back$message)
11.3 处理缺失值
# 处理 NA 值
df <- data.frame(
name = c("Alice", "Bob", NA),
age = c(28, NA, 25)
)
默认将 NA 转换为 null
json_data <- toJSON(df)
print(json_data)
[{"name":"Alice","age":28},{"name":"Bob","age":null},{"name":null,"age":25}]
使用 na 参数控制 NA 的处理方式
json_data2 <- toJSON(df, na = "string")
print(json_data2)
[{"name":"Alice","age":28},{"name":"Bob","age":"NA"},{"name":"NA","age":25}]
12. 与其他包的集成
jsonlite 可以与其他 R 包无缝集成,构建完整的数据处理流程。
12.1 与 dplyr 集成
# 结合 dplyr 进行数据处理
library(dplyr)
读取 JSON 数据
json_data <- '[{"name":"Alice","age":28,"score":85},{"name":"Bob","age":32,"score":92},{"name":"Charlie","age":25,"score":78}]'
df <- fromJSON(json_data)
使用 dplyr 进行数据操作
result <- df %>%
filter(age > 26) %>%
arrange(desc(score)) %>%
select(name, score)
print(result)
将结果写回 JSON
write_json(result, path = "filtered.json", pretty = TRUE)
12.2 与 httr 集成
# 结合 httr 包发送 HTTP 请求
library(httr)
发送 POST 请求并处理 JSON 响应
response <- POST(
url = "https://httpbin.org/post",
body = list(name = "Alice", age = 28),
encode = "json"
)
解析响应
content_data <- content(response, as = "parsed", type = "application/json")
print(content_data$json)
13. 总结
本文系统介绍了 R 语言中 JSON 文件的读写与处理方法,涵盖以下核心内容:
- 基础概念:JSON 的语法结构和数据类型。
- 常用包:jsonlite、rjson、RJSONIO 等包的对比与选择。
- 文件读写:使用
fromJSON()和toJSON()进行 JSON 文件的读取和写入。 - 数据转换:JSON 与 data.frame 之间的相互转换。
- 嵌套处理:处理复杂嵌套 JSON 结构的方法。
- 实战应用:从 API 获取数据、批量处理、性能优化等真实场景。
- 问题解决:编码、特殊字符、缺失值等常见问题的处理方案。
掌握这些技能后,你可以轻松应对日常工作中遇到的 JSON 数据处理需求。建议在实际项目中多加练习,并结合 dplyr、httr 等包构建完整的数据处理流水线。

694

被折叠的 条评论
为什么被折叠?



