Serialize a string with Serde without adding double quotes

44 Views Asked by At

I am trying to serialize an enum into two consecutive csv fields. The first field is a fixed string that depends on the enum variant, the second field is the value in the enum variant, with an extra "Hz" suffix. This is a separate enum type in my code but simplified here as a String.

I have generating Display with the expected format, then using SerializeDisplay. This works however it adds double quotes to the csv field, which I do not want.

How can I serialize a string without serde adding double quotes?

#[derive(SerializeDisplay)]
pub enum Tone {
    Up(String),
    Off,
}

impl Display for Tone {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Tone::Up(s) => write!(f, "TONE,{}Hz", s),
            Tone::Off => write!(f, "OFF,87.5Hz"),
        }
    }
}

fn main() {
        let tone = Tone::Up("hi".to_string());
        let mut wtr = csv::WriterBuilder::new()
            .has_headers(false)
            .from_writer(vec![]);
        wtr.serialize(tone).unwrap();
        let csv = String::from_utf8(wtr.into_inner().unwrap()).unwrap();
        assert_eq!(csv, "TONE,hiHz\n");
}

This results in

assertion `left == right` failed
  left: "\"TONE,hiHz\"\n"
 right: "TONE,hiHz\n"

playground

1

There are 1 best solutions below

0
caiman On

Thanks to @cafce25 and @user1937198 for pointing that the comma I am using to serialize the variant to two csv fields is escaped by serde, and this is what is causing the extra double quotes. To fix this I need to serialize the variant as two fields, by implementing Serialize on the outer struct (not displayed in the original question:

impl Serialize for DrMemory {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("DrMemory", 17)?;
        ...
        match &self.tone {
            Tone::Up(ctcss) => {
                state.serialize_field("TONE", "TONE")?;
                state.serialize_field("Repeater Tone", &format!("{}Hz", ctcss))?;
            }
            ...
            }
        }
        ...
        state.end()
    }
}