Cannot use snake case key name for serde enum

I want to deserialise some config values from TOML using an enum. Not super intuitive, but done.

The problem is that I want the names of the keys representing the enum in my TOML file to be snake case, but I can't get them to deserialise unless they are all one big long word, which is hard to read.

Given:

#[derive(Deserialize)]
#[serde(rename = "Gpu")]
pub struct GpuSettings {
    pub debug_mode: DebugMode, // <-- Why is the enum name being used and not the field name when looking for the key in TOML?
    pub dx12_driver: Dx12Driver,
}

#[derive(Deserialize)]
#[serde(tag = "type")]
pub enum DebugMode { // I really want this to be GpuDebugMode but rename does not work for enums. Why?
    Advanced,
    Standard,
}

#[derive(Deserialize)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum Dx12Driver {
    Fxc,
    StaticDxc,
}

This fails:

[gpu]
debug_mode = "standard"
dx12_driver = "static_dxc"
failed to parse config", source: Some(TomlError { message: "invalid type: string \"standard\", expected internally tagged enum DebugMode

But this is okay:

[gpu]
debugmode = "standard" # But I want they key to be debug_mode
dx12driver = "static_dxc" # But I want the key to be dx12_driver

Why does serde not look for the key name like it does for all other values? Why can I not rename an enum? How do I get it to make the key name snake case?

I'm not sure I understand your problem. Does this do what you want?

use serde::Deserialize;

#[derive(Deserialize, Debug)]
pub struct GpuSettings {
    pub debug_mode: DebugMode,
    pub dx12_driver: Dx12Driver,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum DebugMode {
    Advanced,
    Standard,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Dx12Driver {
    Fxc,
    StaticDxc,
}

#[derive(Deserialize, Debug)]
struct Settings {
    gpu: GpuSettings,
}

fn main() {
    let toml_src = r#"[gpu]
debug_mode = "standard"
dx12_driver = "static_dxc""#;

    let settings: Settings = toml::from_str(toml_src).unwrap();

    println!("{settings:?}");
}

Playground.

1 Like

I think you've mistakenly marked the enum as tagged (as the error implies). See @jofas answer and check the docs

Thanks for the example and pointing out my error.

Yes, I was trying to use an internally tagged enum when I really wanted it to be externally tagged. That was a misunderstanding of the docs on my part.