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.
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:
use pavex::blueprint::Blueprint;
use pavex::request::body::JsonBody;
pub fn blueprint() -> Blueprint {
let mut bp = Blueprint::new();
JsonBody::register(&mut bp); // (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:
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.
// [...]
#[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.