When dealing with JSON in Rust, the first stop is the serde
and serde_json
crates.
serde
provides the basis for serialization in general, while serde_json
provides the specifics for JSON.
Add both crates to your project, and enable the derive
feature for serde
.
❯ cargo add serde serde_json -F serde/derive
Updating crates.io index
Adding serde v1.0.181 to dependencies.
Features:
+ derive
+ serde_derive
+ std
- alloc
- rc
- unstable
Adding serde_json v1.0.104 to dependencies.
Features:
+ std
- alloc
- arbitrary_precision
- float_roundtrip
- indexmap
- preserve_order
- raw_value
- unbounded_depth
Updating crates.io index
Bring serde::Serialize
into scope, and use it as a derive macro on a new struct.
use serde::Serialize;
#[derive(Serialize)]
struct ApiResponse {
data: String,
}
This new struct is our “ApiResponse”. Basically representing the data our API responds with.
Deriving Serialize
enables serializing this struct to a JSON string. The JSON will be structured in the same way as our struct.
Then we can use the struct in our response.
async fn function_handler(
event: Request,
) -> Result<Response<Body>, Error> {
let who = event
.query_string_parameters_ref()
.and_then(|params| params.first("name"))
.unwrap_or("world");
let message = format!(
"Hello {who}, this is an Netlify serverless request"
);
let api_response = ApiResponse { data: message };
let body_text = serde_json::to_string(&api_response)?;
let resp = Response::builder()
.status(200)
.header(CONTENT_TYPE, "application/json")
.body(Body::Text(body_text))?;
Ok(resp)
}
We swap out our html for a regular string showing a message for our JSON response.
Construct an instance of the ApiResponse
with our message as the data, then use serde_json
to serialize that data to a string.
The serialization could fail, so we handle the error with a ?
, which returns the error from our function.
Finally, we need to change the CONTENT_TYPE
header to application/json
and set the new Body::Text
to the body_text
json string.
With cargo lambda watch
and running our invoke again, we get a JSON response.
❯ cargo lambda invoke serverless-intro-netlify --data-file ./fixture.json
{
"statusCode": 200,
"headers":
{
"content-type": "application/json"
},
"multiValueHeaders":
{
"content-type":
[
"application/json"
]
},
"body": "{\"data\":\"Hello chris, this is an Netlify serverless request\"}",
"isBase64Encoded": false
}
In production, we get just the JSON back.
{"data":"Hello chris, this is an Netlify serverless request"}