Search code examples
rustescapingserde-json

Deserializing a Claims field to string returns additional characters


I need to deserialize the following payload, in particular the aud field from a JSON object:

claims: Claims { 
    aud: One("CBr3zBlrKBbwmxOAM1avZQ=="), // 24 len
    // ...
}

claims::aud is an Aud enum:

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum Aud {
    One(String),
    Many(Vec<String>),
}

When I attempt to get a String from serde_json::to_string() it returns two additional characters, an opening and ending char.

use serde_json::Result;

fn aud_from_json(data: &claims::Aud) -> Result<String> {
    let v = serde_json::to_string(&data)?;
    Ok(v.to_owned())
}
let aud = aud_from_json(&token_data.claims.aud)?;
log::debug!("aud field: {:?}\t aud field len({})", &aud, &aud.len());
$ aud field: "\"CBr3zBlrKBbwmxOAM1avZQ==\""         aud field len(26)

It appears there may be trailing escape characters serialized into the string.
Is there a method that can return aud field returned as String, sanitized without extra characters?
e.g. "CBr3zBlrKBbwmxOAM1avZQ=="


Solution

  • The issue was a situation where serde_json::to_string() was mistaken for an actual to_string() implementation, as opposed to a JSON string.

    Extracting an inner member of an enum variant is better done by pattern-matching. Due to the OP's requirements, the last aud member of the Vec is the most important one

    Final implementation (playground):

    use std::io::Result;
    use serde;
    #[macro_use] extern crate serde_derive;
    
    #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
    #[serde(untagged)]
    pub enum Aud {
        One(String),
        Many(Vec<String>),
    }
    
    fn aud_from_json(data: &Aud) -> Result<String> {
        match data {
            Aud::One(audience) => Ok(audience.clone()),
            Aud::Many(audiences) => audiences
              .last()
              .ok_or(std::io::Error::new(std::io::ErrorKind::NotFound, "No audience found"))
              .map(|r| r.clone())
        }
    }