Alex
Alex

Reputation: 377

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=="

Upvotes: 0

Views: 740

Answers (2)

S&#233;bastien Renauld
S&#233;bastien Renauld

Reputation: 19672

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())
    }
}

Upvotes: 1

Jmb
Jmb

Reputation: 23359

If I understood correctly what you said in reply to @SébastienRenauld's answer, you want to base-64 decode the string that's contained in an Aud instance. This can be achieved with:

let aud = Aud::One("CBr3zBlrKBbwmxOAM1avZQ==".to_string());
if let Aud::One(code) = aud {
    let decoded = base64::decode(&code).unwrap();
    log::debug!("Decoded: {:?}", decoded);
}

playground

Upvotes: 0

Related Questions