skip to Main Content

I am delete a key from redis when using rust, this is part of the code looks like:

pub async fn del_redis_key(key: &str,) -> Result<()> {
    let config_redis_string = get_config("redisConnectionStr");
    let redis_con_string: &str = config_redis_string.as_str();
    let redis_client = redis::Client::open(redis_con_string).expect("can create redis client");
    let mut redis_conn = get_con(redis_client);
    let mut redis_conn_unwrap = redis_conn.unwrap();
    let del_result = redis_conn_unwrap.del(key).map_err(RedisCMDError)?;
    FromRedisValue::from_redis_value(&del_result).map_err(|e| RedisTypeError(e).into())
}

now I want to output the delete result del_result as a string, I have tried to convert the result as a json string like this:

let result_json = serde_json::to_string(&del_result).unwrap();
println!("{}",result_json);

it seems did not work because the third party redis lib Value did not implement the serialize trait, the Value code looks like:

#[derive(PartialEq, Eq, Clone)]
pub enum Value {
    /// A nil response from the server.
    Nil,
    /// An integer response.  Note that there are a few situations
    /// in which redis actually returns a string for an integer which
    /// is why this library generally treats integers and strings
    /// the same for all numeric responses.
    Int(i64),
    /// An arbitary binary data.
    Data(Vec<u8>),
    /// A bulk response of more data.  This is generally used by redis
    /// to express nested structures.
    Bulk(Vec<Value>),
    /// A status response.
    Status(String),
    /// A status response which represents the string "OK".
    Okay,
}

is it possible to output the delete result as a string so that I could output into log? I am using the redis lib redis = "0.21.3".

2

Answers


  1. Serde can actually derive for remote structures. Check this link for details: https://serde.rs/remote-derive.html

    But in your particular example, things get a bit more tricky. Because the Value type is recursive (Bulk(Vec<Value>)) and currently you cannot use #[serde(with = ...)] inside a Vec.

    A way out is to define your own serializing function for the whole Vec<Value> type. Here is an example: https://github.com/serde-rs/serde/issues/1211

    I’ve implemented this method for you. It is not quite straightforward though.

    use redis::Value;
    use serde::Serialize;
    
    #[derive(Serialize)]
    #[serde(remote = "Value")]
    pub enum ValueRef {
        Nil,
        Int(i64),
        Data(Vec<u8>),
        #[serde(with = "redis_value_vec")]
        Bulk(Vec<Value>),
        Status(String),
        Okay,
    }
    
    mod redis_value_vec {
        use super::ValueRef;
        use redis::Value;
        use serde::{Serialize, Serializer};
    
        pub fn serialize<S: Serializer>(array: &[Value], serializer: S) -> Result<S::Ok, S::Error> {
            #[derive(Serialize)]
            struct W<'a>(#[serde(with = "ValueRef")] &'a Value);
    
            serializer.collect_seq(array.iter().map(W))
        }
    }
    
    fn main() {
        #[derive(Serialize)]
        struct W<'a>(#[serde(with = "ValueRef")] &'a Value);
    
        let val = Value::Nil;
        println!("{}", serde_json::to_string(&W(&val)).unwrap());
    }
    

    I suggest you submit a PR to that crate, adding a serde feature, optionally enabling this derive. This is very common.

    Login or Signup to reply.
  2. If all you want to do is print out the result for logging purposes, Value implements Debug. So you can print it out with the debug format specifier:

    println!("{:?}", del_result);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search