0Pricing
Learn Rust Coding · Lesson

JSON and State

Shared state and serialization.

JSON and State is a free Learn Rust Coding lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Learn Rust Coding learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Returning JSON

Axum makes JSON responses easy. Wrap any Serialize type in Json and it sets the content type and serializes the body.

use axum::Json;
use serde::Serialize;

#[derive(Serialize)]
struct User { id: u32, name: String }

async fn get_user() -> Json<User> {
    Json(User { id: 1, name: "Alice".into() })
}

Serializing collections

A Vec of serializable items becomes a JSON array. No extra work needed.

use axum::Json;
use serde::Serialize;

#[derive(Serialize)]
struct Item { id: u32 }

async fn list() -> Json<Vec<Item>> {
    Json(vec![Item { id: 1 }, Item { id: 2 }])
}

Modeling JSON in plain Rust

JSON serialization is just turning a struct into a string. With serde_json you call to_string. Here is the idea using a manual format.

struct User { id: u32, name: String }

fn to_json(u: &User) -> String {
    format!("{{\"id\":{},\"name\":\"{}\"}}", u.id, u.name)
}

fn main() {
    let u = User { id: 1, name: "Alice".to_string() };
    println!("{}", to_json(&u));
}

What is shared state?

Shared state is data every handler can access, such as a database pool or config. Axum threads it through with the State extractor.

Defining app state

Define a struct holding your shared data. Often it wraps an Arc so cloning is cheap.

use std::sync::Arc;

#[derive(Clone)]
struct AppState {
    name: Arc<String>,
}

Attaching state to the router

Pass the state to with_state. Axum stores it and provides it to handlers that ask for it.

use axum::{Router, routing::get};

async fn handler() -> &'static str { "ok" }

fn app(state: AppState) -> Router {
    Router::new().route("/", get(handler)).with_state(state)
}

Reading state in a handler

Add a State parameter to receive a clone of your state inside the handler.

use axum::extract::State;

async fn handler(State(state): State<AppState>) -> String {
    state.name.to_string()
}

Mutable shared state

For data that changes, guard it with a lock such as Mutex behind an Arc. This allows safe concurrent mutation.

use std::sync::{Arc, Mutex};

#[derive(Clone)]
struct Counter {
    count: Arc<Mutex<u32>>,
}

Mutating behind a Mutex

Lock the mutex, modify the value, then the guard drops. This runnable example mirrors the increment a handler would perform.

use std::sync::{Arc, Mutex};

fn main() {
    let count = Arc::new(Mutex::new(0u32));
    {
        let mut guard = count.lock().unwrap();
        *guard += 1;
    }
    println!("count = {}", *count.lock().unwrap());
}

Accepting and echoing JSON

Combine input and output JSON: deserialize the body, transform it, and return JSON. A common create-then-respond pattern.

use axum::Json;
use serde::{Serialize, Deserialize};

#[derive(Deserialize)]
struct Input { name: String }
#[derive(Serialize)]
struct Output { greeting: String }

async fn greet(Json(i): Json<Input>) -> Json<Output> {
    Json(Output { greeting: format!("Hi {}", i.name) })
}

Substate with FromRef

When state holds several pieces, derive FromRef so handlers can extract just the part they need.

use axum::extract::FromRef;

#[derive(Clone)]
struct Pool;

#[derive(Clone, FromRef)]
struct AppState {
    pool: Pool,
}

Quick Check

Test your understanding of JSON and state.

Recap

You learned JSON and shared state:

  • Wrap Serialize types in Json to respond
  • Define a Clone state struct, often wrapping Arc
  • Attach it with with_state, read it with State
  • Use Arc<Mutex> for mutable shared data and FromRef for substates

Next: middleware with tower layers.

Frequently asked questions

Is the “JSON and State” lesson free?

Yes — the full text of “JSON and State” is free to read here on the web, and the Learn Rust Coding course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Learn Rust Coding course, upgrade to CoddyKit PRO.

What will I learn in “JSON and State”?

Shared state and serialization. You practise Learn Rust Coding with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Learn Rust Coding?

No prior experience is required. Learn Rust Coding on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “JSON and State” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Learn Rust Coding lesson?

Yes. Every Learn Rust Coding lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Axum Routing
  2. Extractors
  3. JSON and State
  4. Middleware
← Back to Learn Rust Coding