Rust String problem with escape quotes

Hi,

I don't really understand what to do if I build strings because every time I use format! or converting a value into a string with, for example, .to_string() then I always get "\"some string\"". I just want to have "some string".

Here is a code example from me, which show this problem:

fn get_key(&self, key: &str) -> String {
        return format!(r"{}", key);
    }

In my understanding r prevents escaping characters.
Does that happen because I hand over Strings and format them?

My goal is to send keys to redis and use them as keys in the cache.

pub fn set_str(&self,key: &str, value: &str) -> Result<(), ApiError> {
        //let cache_key: String = self.get_key(key);
        let mut cache: PooledConnection<Client> = connection()?;

        cache.set(key, value)?;

        return Ok(());
    }

Another example worked very well:

fn create_user(token: String, change: String) -> CacheEntry {

    let body: String = format!(
        "{{\"token\": {token}, \"change\": {change}, \"data\": [] }}");
    let json: CacheEntry = serde_json::from_str(&body).unwrap();
    
    info!("{:#?}", json);

    return json;
}

r prevents escaping characters in the literal, but it changes nothing in how format works. If there are literal quotes in the value being formatted, they will be in the resulting string. If there are literal backslashes in it, well, you get the point.

Could you share the reproducible example, so that we see the problem in action?

2 Likes

Install redis

Cargo.toml

redis = { version = "0.22.3", features = ["r2d2"] }
r2d2 = "0.8.10"
serde_json = "1"
use lazy_static::lazy_static;
use r2d2::{self, PooledConnection};
use redis::{Client, ConnectionLike, Commands};
use redis::RedisError;
use serde::Deserialize;
use std::fmt;

type Pool = r2d2::Pool<Client>;
pub type CacheConnection = r2d2::PooledConnection<Client>;

#[derive(Debug, Deserialize)]
pub struct ApiError {
    pub status_code: u16,
    pub message: String,
}

impl ApiError {
    pub fn new(status_code: u16, message: String) -> ApiError {
        ApiError { status_code, message }
    }
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.message.as_str())
    }
}

impl From<RedisError> for ApiError {
    fn from(error: RedisError) -> ApiError {
        ApiError::new(500, format!("Redis error: {}", error))
    }
}

lazy_static! {
    static ref POOL: Pool = {
        let redis_url: &str = "redis://127.0.0.1";
        let client = redis::Client::open(redis_url).expect("Failed to create redis client");
        Pool::new(client).expect("Failed to create redis pool")
    };
}

pub fn init() {
    println!("Initializing Cache");
    lazy_static::initialize(&POOL);
    let mut conn: PooledConnection<Client> = connection().expect("Failed to get redis connection");
    assert_eq!(true, conn.check_connection(), "Redis connection check failed");
}

pub fn connection() -> Result<CacheConnection, ApiError> {
    return POOL.get()
        .map_err(|e| api_error::ApiError::new(500, format!("Failed getting db connection: {}", e)));
}

pub fn set_str(key: &str, value: &str) -> Result<(), ApiError> {
        let mut cache: PooledConnection<Client> = connection()?;

        cache.set(key, value)?;

        return Ok(());
    }

fn main() {
       init();
       let key = "foo";
       let value = "bar";
   
       set_str(&key, &value).ok();
}

When you use redis-cli you should see with KEYS * the key as 1) "\"foo\""

Everyone will hate me for this but it works.

I ended up by converting the string into chars and removed the first and last char.

let mut chars = value.chars();
chars.next();
chars.next_back();
chars.as_str()

That sounds like value contains these quote characters. That might be a bug in your program, I'd double check the source and/or parsing of the data.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.