Skip to main content
The Json response type serializes data to JSON and automatically sets the Content-Type: application/json header.

Basic usage

Return any type that implements serde::Serialize:
use axum::{Json, routing::get, Router};
use serde::Serialize;
use uuid::Uuid;

#[derive(Serialize)]
struct User {
    id: Uuid,
    username: String,
}

async fn get_user() -> Json<User> {
    let user = User {
        id: Uuid::new_v4(),
        username: "alice".to_string(),
    };
    Json(user)
}

let app = Router::new().route("/user", get(get_user));

How it works

IntoResponse implementation

The Json type implements IntoResponse by serializing the inner value using serde_json:
impl<T> IntoResponse for Json<T>
where
    T: Serialize,
{
    fn into_response(self) -> Response {
        // Serializes to JSON with initial 128-byte buffer capacity
        // Sets Content-Type: application/json on success
        // Returns 500 Internal Server Error if serialization fails
    }
}
See implementation in axum/src/json.rs:197-232.

Serialization behavior

The serialization process:
  1. Creates a BytesMut buffer with 128-byte initial capacity
  2. Serializes the value using serde_json::to_writer
  3. On success: Returns response with Content-Type: application/json header
  4. On failure: Returns 500 Internal Server Error with error message as plain text

Error handling

If serialization fails (e.g., map with non-string keys), a 500 status code is returned with the error message:
async fn handler() -> Json<HashMap<Vec<u8>, i32>> {
    // This will fail to serialize and return 500
    let map = HashMap::from([(vec![1, 2, 3], 123)]);
    Json(map)
}
To prevent status code override on serialization errors, use ForceStatusCode:
use axum_core::response::ForceStatusCode;
use axum::http::StatusCode;

// Force 418 status even if serialization fails
let response = (
    ForceStatusCode(StatusCode::IM_A_TEAPOT),
    Json(potentially_failing_data),
);

Response fields

Content-Type
header
Automatically set to application/json
body
bytes
The serialized JSON bytes

Common patterns

Returning JSON with custom status

use axum::http::StatusCode;

async fn create_user(/* ... */) -> (StatusCode, Json<User>) {
    let user = create_user_in_db().await;
    (StatusCode::CREATED, Json(user))
}

Returning JSON arrays

async fn list_users() -> Json<Vec<String>> {
    Json(vec!["alice".to_string(), "bob".to_string()])
}

See also