JSON to Rust Struct: GitHub User API

Walk through converting the GitHub /users/{username} response into a complete Rust struct hierarchy with serde, snake_case fields, and Option fields.

Real-World

Detailed Explanation

Real-World Example: GitHub User Endpoint

The GitHub REST API's GET /users/{username} returns a rich JSON payload with nested objects, optional fields, and timestamps. It is a perfect mid-sized example for the converter.

Sample response (trimmed)

{
  "login": "octocat",
  "id": 583231,
  "node_id": "MDQ6VXNlcjU4MzIzMQ==",
  "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
  "html_url": "https://github.com/octocat",
  "type": "User",
  "site_admin": false,
  "name": "The Octocat",
  "company": "@github",
  "blog": "https://github.blog",
  "location": "San Francisco",
  "email": null,
  "bio": null,
  "public_repos": 8,
  "followers": 9001,
  "following": 9,
  "created_at": "2011-01-25T18:44:36Z",
  "updated_at": "2024-05-10T17:20:11Z"
}

Auto-generated Rust (lightly edited)

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GitHubUser {
    pub login: String,
    pub id: i64,
    pub node_id: String,
    pub avatar_url: String,
    pub html_url: String,
    #[serde(rename = "type")]
    pub user_type: String,
    pub site_admin: bool,
    pub name: Option<String>,
    pub company: Option<String>,
    pub blog: Option<String>,
    pub location: Option<String>,
    pub email: Option<String>,
    pub bio: Option<String>,
    pub public_repos: i32,
    pub followers: i32,
    pub following: i32,
    pub created_at: String,
    pub updated_at: String,
}

Notable adjustments

  • The JSON key type collides with a Rust keyword, so the converter emits r#type plus a #[serde(rename = "type")]. The example above renames the field to user_type for readability.
  • name, company, blog, location, email, and bio can be null (some users hide them), so each was promoted to Option<String> after pasting.
  • created_at and updated_at use ISO 8601 strings. To get real DateTime<Utc> values, replace String with chrono::DateTime<chrono::Utc> and add chrono = { version = "0.4", features = ["serde"] } to Cargo.toml.

Calling the API

let resp: GitHubUser = reqwest::get("https://api.github.com/users/octocat")
    .await?
    .json()
    .await?;

println!("{} has {} followers", resp.login, resp.followers);

Lessons learned

This single endpoint exercises six features of the converter at once: snake_case mapping, integer width selection, Option promotion, keyword escape, struct naming, and serde derives. Use it as the template for your own real-world API client work.

Use Case

Building Rust GitHub clients, status dashboards, contributor analytics tools, or anything else that consumes the GitHub REST API. The same workflow applies to the GitLab, Bitbucket, and Forgejo APIs with minor adjustments.

Try It — JSON to Rust Struct Converter

Open full tool