Работа с JSON
Волга упрощает работу с JSON в ваших веб-приложениях, как для приема входящих JSON в запросах, так и для отправки JSON-ответов.
Получение JSON
Чтобы принять JSON в теле запроса и десериализовать его в строго типизированную сущность, используйте структуру Json<T>
. Тип T
должен быть десериализуемой структурой, поэтому убедитесь, что он реализует типаж Deserialize
из serde:
use volga::{App, Json, ok};
use serde::Deserialize;
#[derive(Deserialize)]
struct User {
name: String,
age: i32
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut app = App::new();
// POST /hello
// { name: "John", age: 35 }
app.map_post("/hello", |user: Json<User>| async move {
ok!("Привет, {}!", user.name)
});
app.run().await
}
Для тестирования можно использовать команду curl
следующим образом:
curl -X POST "http://127.0.0.1:7878/hello" -H "Content-Type: application/json" -d "{ \"name\": \"John\", \"age\": 35 }"
Привет, John!
Совет
Вы можете обернуть поля вашей структуры в Option<T>
, как описано в разделе Обработка опциональных параметров запроса.
Отправка JSON
Для отправки ответов в формате JSON Волга предоставляет несколько удобных методов:
Использование Results::from()
Метод Results::from()
, который был описан ранее, автоматически сериализует переданную структуру в JSON.
Использование Results::json()
Метод Results::json()
напрямую сериализует структуры Rust в JSON. Убедитесь, что ваша структура реализует trait Serialize
:
use volga::{App, Results};
use serde::Serialize;
#[derive(Serialize)]
struct User {
name: String,
age: i32
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut app = App::new();
app.map_get("/hello", || async {
let user: User = User {
name: "John".into(),
age: 35
};
Results::json(user)
});
app.run().await
}
Проверяем:
> curl http://127.0.0.1:7878/hello
{"name":"John","age":35}
Упрощенная версия с макросом ok!
Для более компактного подхода используйте макрос ok!
, который автоматически компилируется в Results::json()
, если передать сериализуемый объект:
use volga::{App, ok};
use serde::Serialize;
#[derive(Serialize)]
struct User {
name: String,
age: i32
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut app = App::new();
app.map_get("/hello", || async {
let user: User = User {
name: "John".into(),
age: 35
};
ok!(user)
});
app.run().await
}
Кроме того, с помощью макроса ok!
можно использовать и неструктурированные JSON-данные:
use volga::{App, ok};
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut app = App::new();
app.map_get("/hello", || async {
ok!({ name: "John", age: 35 })
});
app.run().await
}
Указание статуса вместе с JSON
Вы также можете включать HTTP-статусы в ваши JSON-ответы с помощью макроса status!
:
use volga::{App, status};
use serde::Serialize;
#[derive(Serialize)]
struct User {
name: String,
age: i32
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut app = App::new();
app.map_get("/hello", || async {
let user: User = User {
name: "John".into(),
age: 35
};
status!(200, user)
});
app.run().await
}
Тело JSON можно дополнить стандартными HTTP-статусами, такими как 200
, 400
, 401
, 403
и другими, чтобы предоставлять понятные сообщения для клиента.
Вот полный пример.