Volga
Home
API Docs
GitHub
  • English
  • Русский
Home
API Docs
GitHub
  • English
  • Русский
  • Home
  • Basics

    • Quick Start
    • Route Parameters
    • Query Parameters
    • Route Groups
    • Headers
  • Data Formats

    • Handling JSON
    • Handling Form Data
    • Working with Files
    • Server-Sent Events (SSE)
  • Protocols

    • HTTP/1 and HTTP/2
    • HTTPS
    • WebSockets & WebTransport
  • Advanced

    • Custom Middleware
    • Response Compression
    • Request Decompression
    • Global Error Handling
    • Dependency Injection
    • Tracing & Logging
    • Static Files
    • CORS (Cross-Origin Resource Sharing)
    • Cookies
    • Request cancellation
    • Custom Handling of HEAD, OPTIONS, and TRACE Methods

Handling JSON

Volga simplifies the process of dealing with JSON data in your web applications, both for ingesting incoming JSON payloads in requests and sending JSON responses.

Receiving JSON Data

To accept a JSON body in a request and deserialize it into a strongly-typed entity, use the Json<T> struct. Where T should be a deserializable struct, so ensure it derives from Deserialize from 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!("Hello {}!", user.name)
    });

    app.run().await
}

To test this endpoint, you can use the curl command like this:

curl -X POST "http://127.0.0.1:7878/hello" -H "Content-Type: application/json" -d "{ "name": "John", "age": 35 }"
Hello John!

Tips

You can wrap your struct fields into Option<T> as similar as described for Optional Query Params

Sending JSON Responses

To send responses as JSON, Volga provides a couple of convenient methods:

Using Results::from()

The Results::from() method can be used, which has been described earlier, and the struct instance passed will be automatically serialized to JSON.

Using Results::json()

The Results::json() method directly serializes Rust structs into JSON output. Ensure your struct implements 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
}

To see the JSON response in action:

> curl http://127.0.0.1:7878/hello
{"name":"John","age":35}

Simplified Version with ok! Macro

For a more streamlined approach, the ok! macro automatically compiles into Results::json() under the hood when passing a serializable object:

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
}

Moreover, with the ok! macro you can also use the untyped 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
}

Using Status with JSON

You can also include HTTP status codes in your JSON responses using the status! macro:

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
}

The JSON body can be coupled with standard HTTP statuses such as 200, 400, 401, 403 and others to provide clear client-side messages.

Here is the full example

Last Updated:
Next
Handling Form Data