Serialize struct into strange json format: serialize inner struct's name

I don't know how to phrase the question better. Sorry.

I have to generate the following json.

[
  "commandName",
  {
    "parameter1": "value1",
    "parameter2": "value2"
   },
   "tag1"
]

The set of parameters depends on the command.

I defined the types

#![derive(Serialize)]
struct CommandName {
   parameter1: String,
   parameter2: String,
}
struct<a', T> Request {
  tag: &'a str,
  command: T
}

and tried to serialize using the following code.

impl<'a, T> Serialize for Request<'a, T>
where
    T: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer
    {
        let mut tup = serializer.serialize_tuple(3)?;
        tup.serialize_element("commandName")?;
        tup.serialize_element(&self.req)?;
        tup.serialize_element(self.tag)?;
        tup.end()
    }
}

The Problem is that I cannot get commandName from self.req.

I might be able not to use a struct CommandName, but an enum encompassing all possible commands, but that will make it harder in other parts of the code.

Any idea? I would prefer not having to use proc macros.

I'd advise you go the enum route regardless, but you could do something like this:

#[derive(Serialize, Debug, Default)]
struct Foo(String, CommandName, String);

#[derive(Serialize, Debug, Default)]
struct CommandName {
    parameter1: String,
    parameter2: String,
}

serde_json::to_string_pretty(&Foo::default()).unwrap()
/*
[
  "",
  {
    "parameter1": "",
    "parameter2": ""
  },
  ""
]
*/

In any case, don't use borrowed strings here.

Thank you for your reply.

I would really like to avoid having to hard code commandName. It should come from the struct's name CommandName. Is that possible without too much effort?

I modified your original code to make use of this helper function : Rust Playground

Thanks! This works beautifully. I used the linked crate in the answer https://crates.io/crates/serde_type_name.

That's a ton of code for such a trivial requirement. If you need to retrieve a type based on a name, use an associated const instead: Playground

1 Like

All these lines add up if you want to serialize all requests in https://doc.dovecot.org/admin_manual/doveadm_http_api/.

That's probably a good use case for a macro (declarative if you own the types, or perhaps a custom derive if you don't).