JSON处理 #
JSON是现代Web API中最常用的数据交换格式。Rocket通过serde库提供了强大的JSON处理能力。
基本配置 #
添加依赖 #
toml
[dependencies]
rocket = { version = "0.5", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
JSON请求 #
定义数据结构 #
rust
use rocket::serde::{Deserialize, Serialize};
use rocket::serde::json::Json;
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
id: u32,
name: String,
email: String,
}
接收JSON请求 #
rust
#[post("/users", format = "json", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
println!("Creating user: {:?}", user);
user
}
可选JSON字段 #
rust
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct UpdateUser {
name: Option<String>,
email: Option<String>,
}
#[patch("/users/<id>", format = "json", data = "<data>")]
fn update_user(id: u32, data: Json<UpdateUser>) -> String {
format!("Updating user {}: {:?}", id, data)
}
JSON响应 #
返回JSON #
rust
#[get("/users/<id>")]
fn get_user(id: u32) -> Json<User> {
Json(User {
id,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
})
}
返回JSON数组 #
rust
#[get("/users")]
fn list_users() -> Json<Vec<User>> {
Json(vec![
User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string() },
User { id: 2, name: "Bob".to_string(), email: "bob@example.com".to_string() },
])
}
条件JSON响应 #
rust
use rocket::http::Status;
#[get("/users/<id>")]
fn get_user(id: u32) -> Result<Json<User>, Status> {
if id == 0 {
Err(Status::NotFound)
} else {
Ok(Json(User {
id,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
}))
}
}
高级序列化 #
自定义序列化 #
rust
use rocket::serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
#[serde(rename = "userId")]
id: u32,
#[serde(rename = "fullName")]
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
email: Option<String>,
#[serde(default)]
role: String,
}
枚举序列化 #
rust
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
enum Status {
#[serde(rename = "active")]
Active,
#[serde(rename = "inactive")]
Inactive,
#[serde(rename = "pending")]
Pending,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct UserStatus {
user_id: u32,
status: Status,
}
嵌套结构 #
rust
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct Address {
street: String,
city: String,
country: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct UserWithAddress {
id: u32,
name: String,
address: Address,
}
错误处理 #
自定义错误响应 #
rust
use rocket::serde::{Deserialize, Serialize};
use rocket::serde::json::Json;
use rocket::http::Status;
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct ErrorResponse {
error: String,
code: u16,
}
#[derive(Debug, Deserialize)]
#[serde(crate = "rocket::serde")]
struct CreateUser {
name: String,
email: String,
}
#[post("/users", format = "json", data = "<data>")]
fn create_user(data: Json<CreateUser>) -> Result<Json<User>, (Status, Json<ErrorResponse>)> {
if data.name.is_empty() {
return Err((
Status::BadRequest,
Json(ErrorResponse {
error: "Name cannot be empty".to_string(),
code: 400,
}),
));
}
Ok(Json(User {
id: 1,
name: data.name.clone(),
email: data.email.clone(),
}))
}
验证错误 #
rust
use rocket::serde::{Deserialize, Serialize};
use validator::Validate;
#[derive(Debug, Deserialize, Validate)]
#[serde(crate = "rocket::serde")]
struct ValidatedUser {
#[validate(length(min = 3, max = 20))]
name: String,
#[validate(email)]
email: String,
}
#[post("/users/validate", format = "json", data = "<data>")]
fn validate_user(data: Json<ValidatedUser>) -> Result<Json<User>, (Status, Json<ErrorResponse>)> {
data.validate()
.map_err(|e| {
(
Status::BadRequest,
Json(ErrorResponse {
error: e.to_string(),
code: 400,
}),
)
})?;
Ok(Json(User {
id: 1,
name: data.name.clone(),
email: data.email.clone(),
}))
}
JSON值处理 #
动态JSON #
rust
use rocket::serde::json::{Json, Value};
#[post("/echo", format = "json", data = "<data>")]
fn echo_json(data: Json<Value>) -> Json<Value> {
data
}
#[post("/transform", format = "json", data = "<data>")]
fn transform_json(data: Json<Value>) -> Json<Value> {
let mut value = data.into_inner();
if let Some(obj) = value.as_object_mut() {
obj.insert("processed".to_string(), Value::Bool(true));
}
Json(value)
}
分页响应 #
rust
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct PaginatedResponse<T> {
data: Vec<T>,
page: u32,
per_page: u32,
total: u32,
total_pages: u32,
}
#[get("/users?<page>&<per_page>")]
fn paginated_users(page: Option<u32>, per_page: Option<u32>) -> Json<PaginatedResponse<User>> {
let page = page.unwrap_or(1);
let per_page = per_page.unwrap_or(10);
Json(PaginatedResponse {
data: vec![
User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string() },
],
page,
per_page,
total: 100,
total_pages: 10,
})
}
完整示例 #
rust
#[macro_use] extern crate rocket;
use rocket::serde::{Deserialize, Serialize};
use rocket::serde::json::Json;
use rocket::http::Status;
use std::collections::HashMap;
use std::sync::Mutex;
use rocket::State;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
id: u32,
name: String,
email: String,
}
#[derive(Debug, Deserialize)]
#[serde(crate = "rocket::serde")]
struct CreateUser {
name: String,
email: String,
}
#[derive(Debug, Serialize)]
#[serde(crate = "rocket::serde")]
struct ErrorResponse {
error: String,
code: u16,
}
type Db = Mutex<HashMap<u32, User>>;
#[get("/users")]
fn list_users(db: &State<Db>) -> Json<Vec<User>> {
let users = db.lock().unwrap();
Json(users.values().cloned().collect())
}
#[get("/users/<id>")]
fn get_user(id: u32, db: &State<Db>) -> Result<Json<User>, (Status, Json<ErrorResponse>)> {
let users = db.lock().unwrap();
users.get(&id)
.cloned()
.map(Json)
.ok_or_else(|| {
(
Status::NotFound,
Json(ErrorResponse {
error: format!("User {} not found", id),
code: 404,
}),
)
})
}
#[post("/users", format = "json", data = "<data>")]
fn create_user(
data: Json<CreateUser>,
db: &State<Db>,
) -> Result<Json<User>, (Status, Json<ErrorResponse>)> {
if data.name.is_empty() {
return Err((
Status::BadRequest,
Json(ErrorResponse {
error: "Name cannot be empty".to_string(),
code: 400,
}),
));
}
let mut users = db.lock().unwrap();
let id = (users.len() + 1) as u32;
let user = User {
id,
name: data.name.clone(),
email: data.email.clone(),
};
users.insert(id, user.clone());
Ok(Json(user))
}
#[put("/users/<id>", format = "json", data = "<data>")]
fn update_user(
id: u32,
data: Json<CreateUser>,
db: &State<Db>,
) -> Result<Json<User>, (Status, Json<ErrorResponse>)> {
let mut users = db.lock().unwrap();
if let Some(user) = users.get_mut(&id) {
user.name = data.name.clone();
user.email = data.email.clone();
Ok(Json(user.clone()))
} else {
Err((
Status::NotFound,
Json(ErrorResponse {
error: format!("User {} not found", id),
code: 404,
}),
))
}
}
#[delete("/users/<id>")]
fn delete_user(id: u32, db: &State<Db>) -> Result<Status, (Status, Json<ErrorResponse>)> {
let mut users = db.lock().unwrap();
if users.remove(&id).is_some() {
Ok(Status::NoContent)
} else {
Err((
Status::NotFound,
Json(ErrorResponse {
error: format!("User {} not found", id),
code: 404,
}),
))
}
}
#[launch]
fn rocket() -> _ {
rocket::build()
.manage(Mutex::new(HashMap::<u32, User>::new()))
.mount("/api", routes![
list_users,
get_user,
create_user,
update_user,
delete_user
])
}
测试示例 #
bash
# 创建用户
curl -X POST http://127.0.0.1:8000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}'
# 获取用户列表
curl http://127.0.0.1:8000/api/users
# 获取单个用户
curl http://127.0.0.1:8000/api/users/1
# 更新用户
curl -X PUT http://127.0.0.1:8000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Alice Updated","email":"alice.updated@example.com"}'
# 删除用户
curl -X DELETE http://127.0.0.1:8000/api/users/1
下一步 #
掌握了JSON处理后,让我们继续学习 文件上传,了解如何处理文件上传请求。
最后更新:2026-03-28