Back to Blog

Rust JSON Config Loader | serde & serde_json Tutorial | Rust by Examples

Sandy LaneSandy Lane

Video: Rust JSON Config Loader | serde & serde_json Tutorial | Rust by Examples by Taught by Celeste AI - AI Coding Coach

Watch full page →

Rust JSON Config Loader with serde & serde_json

In this tutorial, you'll learn how to load and parse JSON configuration files in Rust using the powerful serde and serde_json crates. We'll cover defining structs that mirror JSON data, handling optional fields, and setting default values to build a flexible config loader.

Code

use serde::Deserialize;
use std::fs;

// Define the main config struct matching the JSON structure
#[derive(Deserialize, Debug)]
struct Config {
  app_name: String,
  version: Option,           // Optional field
  #[serde(default)]                  // Uses default if missing
  debug_mode: bool,
  #[serde(default = "default_max_connections")] // Custom default function
  max_connections: u32,
  #[serde(default)]                  // Optional nested struct
  database: Option,
}

// Nested struct for database settings
#[derive(Deserialize, Debug)]
struct DatabaseConfig {
  host: String,
  port: u16,
  user: String,
  password: String,
}

// Custom default value for max_connections
fn default_max_connections() -> u32 {
  10
}

fn main() {
  // Read the JSON config file as a string
  let config_data = fs::read_to_string("config.json")
    .expect("Failed to read config file");

  // Parse JSON string into Config struct
  let config: Config = serde_json::from_str(&config_data)
    .expect("Failed to parse JSON");

  // Access and print config values
  println!("App Name: {}", config.app_name);
  println!("Version: {}", config.version.unwrap_or("N/A".to_string()));
  println!("Debug Mode: {}", config.debug_mode);
  println!("Max Connections: {}", config.max_connections);

  if let Some(db) = config.database {
    println!("Database Host: {}", db.host);
    println!("Database Port: {}", db.port);
  } else {
    println!("No database config provided");
  }
}

Key Points

  • Use #[derive(Deserialize)] to automatically generate code to parse JSON into Rust structs.
  • Optional fields can be represented with Option<T>, allowing JSON keys to be missing safely.
  • The #[serde(default)] attribute provides default values for missing fields, either via type defaults or custom functions.
  • Nested JSON objects map naturally to nested Rust structs for organized configuration.
  • serde_json::from_str parses JSON strings into Rust data structures, with error handling via expect or match.