diff --git a/backend/src/models/config.rs b/backend/src/models/config.rs index f1a9b147..7c48c2da 100644 --- a/backend/src/models/config.rs +++ b/backend/src/models/config.rs @@ -36,8 +36,16 @@ impl Config { pub fn load(config_path: &PathBuf) -> anyhow::Result { if config_path.exists() { let content = std::fs::read_to_string(config_path)?; - let config: Config = serde_json::from_str(&content)?; - Ok(config) + + // Try to deserialize as is first + match serde_json::from_str::(&content) { + Ok(config) => Ok(config), + Err(_) => { + // If full deserialization fails, merge with defaults + let config = Self::load_with_defaults(&content, config_path)?; + Ok(config) + } + } } else { let config = Config::default(); config.save(config_path)?; @@ -45,6 +53,40 @@ impl Config { } } + fn load_with_defaults(content: &str, config_path: &PathBuf) -> anyhow::Result { + // Parse as generic JSON value + let existing_value: serde_json::Value = serde_json::from_str(content)?; + + // Get default config as JSON value + let default_config = Config::default(); + let default_value = serde_json::to_value(&default_config)?; + + // Merge existing config with defaults + let merged_value = Self::merge_json_values(default_value, existing_value); + + // Deserialize merged value back to Config + let config: Config = serde_json::from_value(merged_value)?; + + // Save the updated config with any missing defaults + config.save(config_path)?; + + Ok(config) + } + + fn merge_json_values(mut base: serde_json::Value, overlay: serde_json::Value) -> serde_json::Value { + match (&mut base, overlay) { + (serde_json::Value::Object(base_map), serde_json::Value::Object(overlay_map)) => { + for (key, value) in overlay_map { + base_map.entry(key).and_modify(|base_value| { + *base_value = Self::merge_json_values(base_value.clone(), value.clone()); + }).or_insert(value); + } + base + } + (_, overlay) => overlay, // Use overlay value for non-objects + } + } + pub fn save(&self, config_path: &PathBuf) -> anyhow::Result<()> { let content = serde_json::to_string_pretty(self)?; std::fs::write(config_path, content)?;