# Send and receive JSON

**For:** Rust developers talking to a JSON API.

You post a Rust struct as JSON and read the answer back into another struct, using serde on both ends.

Before you start: you need Rust with Cargo. fibre_http comes from crates.io as `fibre_http = "0"`.

## Set up the project

Start a new binary crate.

```sh
cargo new todo_client
cd todo_client
```

Put this in the `[dependencies]` section of `Cargo.toml`:

```toml title="Cargo.toml"
[dependencies]
fibre_http = { version = "0", features = ["json"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
```

## The program

httpbin.org's `/post` endpoint sends back whatever JSON it received under a `json` field. That makes it a handy stand-in for a real API. Replace `src/main.rs` with this:

```rust title="src/main.rs"
use fibre_http::AsyncClient;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct NewTodo {
    title: String,
    done: bool,
}

#[derive(Deserialize, Debug)]
struct Echo {
    json: NewTodo,
}

#[tokio::main]
async fn main() -> Result<(), fibre_http::Error> {
    let client = AsyncClient::new();
    let todo = NewTodo { title: "write the http tutorial".to_string(), done: false };

    let response = client.post("https://httpbin.org/post").json(&todo).send().await?.error_for_status()?;
    println!("status: {}", response.status());

    let echo: Echo = response.json().await?;
    println!("the server received: {:?}", echo.json);
    Ok(())
}
```

Run it:

```shell-session
$ cargo run
status: 200 OK
the server received: NewTodo { title: "write the http tutorial", done: false }
```

## What each part does

`json(&todo)` on the request turns the struct into JSON with serde and sets `Content-Type: application/json`. Any type that implements `Serialize` works.

`json()` on the response reads the whole body and turns it into any type that implements `Deserialize`. Fields the struct does not name are skipped, which is why `Echo` only needs `json` out of httpbin's longer answer.

If the body is not valid JSON for that type, `json()` returns an error instead of a half-filled struct.

## Where to go next

The usage guide covers the other ways to send a body: [https://github.com/excsn/fibre/blob/main/http/README.USAGE.md](https://github.com/excsn/fibre/blob/main/http/README.USAGE.md)
