Ruby JSON
在 Ruby 中,JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,常用于 Web 应用程序的 API 数据传输、配置文件存储等。Ruby 提供了内置的 json
库来解析和生成 JSON 数据,简单高效。以下是对 Ruby JSON 处理的中文讲解,涵盖核心概念、解析与生成 JSON、常用方法、示例代码及注意事项,力求简洁清晰。
1. JSON 简介
JSON 是一种基于文本的格式,用于表示结构化数据,支持对象(键值对)、数组、字符串、数字、布尔值和 null
。Ruby 的 json
库提供了将 Ruby 对象转换为 JSON 字符串(序列化)以及将 JSON 字符串解析为 Ruby 对象(反序列化)的功能。
特点:
- 跨语言支持,适合 API 和数据交换。
- 轻量,易于阅读和解析。
- Ruby 的
json
库是标准库,无需额外安装。
2. 安装与引入
json
库是 Ruby 标准库的一部分,无需安装,直接引入:
require 'json'
验证:
puts JSON::VERSION # 输出:2.6.3(示例版本,视 Ruby 版本而定)
3. 生成 JSON(序列化)
将 Ruby 对象(如哈希、数组)转换为 JSON 字符串。
基本方法
JSON.generate(obj)
:将对象转换为 JSON 字符串。obj.to_json
:对象调用to_json
方法,生成 JSON。
示例
require 'json'
# Ruby 哈希
data = {
name: "Alice",
age: 30,
hobbies: ["reading", "coding"],
address: { city: "Beijing", country: "China" }
}
# 生成 JSON
json_str = JSON.generate(data)
puts json_str
# 简写
puts data.to_json
输出:
{"name":"Alice","age":30,"hobbies":["reading","coding"],"address":{"city":"Beijing","country":"China"}}
格式化输出
使用 JSON.pretty_generate
生成带缩进的 JSON,便于阅读:
puts JSON.pretty_generate(data)
输出:
{
"name": "Alice",
"age": 30,
"hobbies": [
"reading",
"coding"
],
"address": {
"city": "Beijing",
"country": "China"
}
}
4. 解析 JSON(反序列化)
将 JSON 字符串转换为 Ruby 对象(通常是哈希或数组)。
基本方法
JSON.parse(str)
:解析 JSON 字符串,返回 Ruby 对象。- 选项:
symbolize_names: true
:将键转换为符号。allow_nan: true
:允许解析 NaN、Infinity 等非标准值。
示例
require 'json'
json_str = '{"name":"Alice","age":30,"hobbies":["reading","coding"]}'
# 解析为哈希(键为字符串)
data = JSON.parse(json_str)
puts data["name"] # 输出:Alice
# 解析为哈希(键为符号)
data = JSON.parse(json_str, symbolize_names: true)
puts data[:name] # 输出:Alice
5. 处理复杂对象
Ruby 的 json
库支持大多数 Ruby 对象,但自定义对象需实现 to_json
方法。
自定义对象
require 'json'
class User
def initialize(name, age)
@name = name
@age = age
end
def to_json(*args)
{ name: @name, age: @age }.to_json(*args)
end
end
user = User.new("Alice", 30)
puts JSON.generate(user)
输出:
{"name":"Alice","age":30}
6. 异常处理
解析 JSON 时可能因格式错误抛出异常,需妥善处理。
require 'json'
begin
JSON.parse("invalid json") # 无效 JSON
rescue JSON::ParserError => e
puts "解析错误: #{e.message}"
end
输出:
解析错误: unexpected token at 'invalid json'
常见异常:
JSON::ParserError
:JSON 格式错误。JSON::NestingError
:嵌套层次过深。TypeError
:尝试序列化不支持的对象类型。
7. 结合 Web 应用
JSON 常用于 Web API(如 RESTful 服务)。以下示例展示如何结合 net/http
获取和解析 JSON。
require 'json'
require 'net/http'
uri = URI('https://jsonplaceholder.typicode.com/users/1')
response = Net::HTTP.get(uri)
user = JSON.parse(response, symbolize_names: true)
puts "Name: #{user[:name]}, Email: #{user[:email]}"
输出(示例):
Name: Leanne Graham, Email: Sincere@april.biz
8. 注意事项
- 编码:
- JSON 默认使用 UTF-8,确保输入字符串编码正确:
ruby JSON.parse(str, encoding: 'UTF-8')
- 处理非 UTF-8 数据时,需转码:
ruby str.encode('UTF-8', 'ISO-8859-1')
- 性能:
- 大型 JSON 数据解析可能较慢,考虑流式解析(
JSON::Stream
gem)。 - 缓存频繁使用的 JSON 结果。
- 安全性:
- 解析外部 JSON 时,验证数据格式,防止注入攻击。
- 避免序列化敏感数据(如密码)。
- 对象支持:
- 仅支持基本类型(字符串、数字、布尔值、数组、哈希、null)。
- 自定义对象需定义
to_json
方法。 - 调试:
- 使用
pretty_generate
检查 JSON 结构。 - 捕获
JSON::ParserError
定位错误。 - 现代替代:
- Rails 的
ActiveSupport::JSON
提供额外功能。 - 复杂 API 推荐使用
httparty
或faraday
。
9. 综合示例
以下示例实现一个简单的 JSON 数据处理器,结合文件读写和 HTTP 请求。
require 'json'
require 'net/http'
# 保存用户数据到 JSON 文件
users = [
{ id: 1, name: "Alice", age: 30 },
{ id: 2, name: "Bob", age: 25 }
]
# 写入文件
File.write('users.json', JSON.pretty_generate(users))
puts "已保存到 users.json"
# 读取并解析文件
data = JSON.parse(File.read('users.json'), symbolize_names: true)
puts "读取用户: #{data.map { |u| u[:name] }.join(', ')}"
# 从 API 获取数据
begin
uri = URI('https://jsonplaceholder.typicode.com/users')
response = Net::HTTP.get(uri)
api_users = JSON.parse(response, symbolize_names: true)
puts "API 用户: #{api_users.first[:name]}"
rescue JSON::ParserError => e
puts "API 解析错误: #{e.message}"
rescue => e
puts "其他错误: #{e.message}"
end
输出:
已保存到 users.json
读取用户: Alice, Bob
API 用户: Leanne Graham
保存的 users.json:
[
{
"id": 1,
"name": "Alice",
"age": 30
},
{
"id": 2,
"name": "Bob",
"age": 25
}
]
10. 总结
Ruby 的 json
库通过 JSON.generate
和 JSON.parse
提供高效的 JSON 序列化和反序列化功能,支持哈希、数组等基本类型。结合 pretty_generate
和 symbolize_names
优化开发体验。注意编码一致性、异常处理和安全性,适合 API 数据处理、配置文件管理等场景。复杂 Web 应用可结合 httparty
或 Rails 增强功能。
如果你需要更复杂的 JSON 示例(如流式解析、复杂对象序列化)或有其他问题,请告诉我!