Keep the tag when deserializing a JSON with Serde

I want to deserialize a JSON like this:

{"token": "abc", "action": "set_value", "val": "foo"}

token and action are always there and determine which other parameters are valid.

The code I'm using:

use serde::{Deserialize};

#[derive(Deserialize, Debug)]
#[serde(tag = "action")]
enum ActionType {
    #[serde(rename = "greet")]
    Greet,
    #[serde(rename = "set_value")]
    SetValue {
        val: String,
    },
}

#[derive(Deserialize, Debug)]
struct RequestJson {
    token: String,
    #[serde(flatten)]
    action_type: ActionType,
}

fn main() {
    let r: RequestJson = serde_json::from_str(r#"{"token": "abc", "action": "set_value", "val": "foo"}"#).unwrap();
    println!("{:#?}", r);
}

Playground

But now I would like to log each of those requests and I'd like to log which action they contained:

fn main() {
    let r: RequestJson = serde_json::from_str(r#"{"token": "abc", "action": "set_value", "val": "foo"}"#).unwrap();
    eprintln!("Request received, action = {}", "???");
    println!("{:#?}", r);
}

I'd like to keep the action keys ("greet", "set_value") in one place only, not having a separate mapping which could introduce errors.

Is that possible?

I don't see a "separate mapping" in the code you posted. What are you doing currently? And since you have already parsed the enum, why aren't you matching on it as opposed to trying to keep the raw string around?

Where I'm currently (see Playground) logging

Request received, action = ???

I would like to log

Request received, action = set_value

instead.

Possibly you could use a macro as demonstrated in this playground.