Skip to content

JSON

You can use JsonBody<T> to work with JSON-encoded request bodies.
JsonBody<T> parses the raw JSON into an instance of the type T you specified.

src/json/routes.rs
use pavex::http::StatusCode;
use pavex::request::body::JsonBody;

#[derive(serde::Deserialize)]
pub struct HomeListing {
    address: String,
    price: u64,
}

pub fn handler(body: &JsonBody<HomeListing>) -> StatusCode {
    println!(
        "The home you are looking for is located in {} and it's being sold for ${}",
        body.0.address, body.0.price
    );
    // [...]
}

The whole request body is buffered in memory before being deserialized.

Registration

If you're using the default ApiKit, you don't need to register a constructor for JsonBody: it's already included in the kit.

If you're not using ApiKit, you need to register a constructor for JsonBody<T>. You can use JsonBody::register to register the default constructor and error handler:

src/blueprint.rs
use pavex::blueprint::Blueprint;
use pavex::request::body::JsonBody;

pub fn blueprint() -> Blueprint {
    let mut bp = Blueprint::new();
    JsonBody::register(&mut bp); // (1)!
    // [...]
}
  1. You also need to register a constructor for BufferedBody!
    Check out the BufferedBody guide for more details.

Extraction

Inject JsonBody<T> as an input in your components to access the parsed body:

src/json/routes.rs
use pavex::http::StatusCode;
use pavex::request::body::JsonBody;

#[derive(serde::Deserialize)]
pub struct HomeListing {
    address: String,
    price: u64,
}

pub fn handler(body: &JsonBody<HomeListing>) -> StatusCode {
    println!(
        "The home you are looking for is located in {} and it's being sold for ${}",
        body.0.address, body.0.price
    );
    // [...]
}

Deserialization

The newly defined struct must be deserializable—i.e. it must implement the serde::Deserialize trait.
You can derive serde::Deserialize in most cases.

src/json/routes.rs
// [...]
#[derive(serde::Deserialize)]
pub struct HomeListing {
    address: String,
    price: u64,
}

Avoiding allocations

If you want to minimize memory usage, you can try to avoid unnecessary heap memory allocations when deserializing string-like fields from the body of the incoming request. Pavex supports this use case—you can borrow from the request body.

Escape sequences

It is not always possible to avoid allocations, though. In particular, Pavex must allocate a new String if the JSON string you are trying to deserialize contains escape sequences, such as \n or a \". Using a &str in this case would result in a runtime error when attempting the deserialization.

Cow

We recommend using Cow<'_, str> as your field type for string-like parameters. It borrows from the request's body if possible, it allocates a new String if it can't be avoided.

Cow<'_, str> strikes a balance between performance and robustness: you don't have to worry about a runtime error if the field contains escape sequences, but you tried to use &str as its field type.