Skip to main content

rustis/resp/
json.rs

1use serde::{
2    Deserialize,
3    de::{self},
4    ser::Serialize,
5};
6
7/// Wrapper type that deserializes a Redis bulk string as JSON into a Rust value.
8///
9/// This is useful for retrieving structured data from Redis that was stored as JSON.
10/// Typically used with commands like `GET`, `HGET`, or any command returning a bulk string.
11///
12/// # Example
13/// ```rust
14/// use rustis::{
15///     client::Client,
16///     commands::{FlushingMode, ServerCommands, StringCommands},
17///     resp::{Json, JsonRef},
18///     Result
19/// };
20///
21/// #[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
22/// struct User {
23///     id: u32,
24///     name: String,
25/// }
26///
27/// #[cfg_attr(feature = "tokio-runtime", tokio::main)]
28/// #[cfg_attr(feature = "async-std-runtime", async_std::main)]
29/// async fn main() -> Result<()> {
30///     let client = Client::connect("127.0.0.1:6379").await?;
31///     client.flushall(FlushingMode::Sync).await?;
32///     let user1 = User { id: 12, name: "foo".to_string() };
33///     client.set("user:123", JsonRef(&user1)).await;
34///     let Json(user2): Json<User> = client.get("user:123").await?;
35///
36///     assert_eq!(user1, user2);
37///     Ok(())
38/// }
39/// ```
40#[derive(Debug, Clone)]
41#[must_use]
42pub struct Json<T>(pub T);
43
44impl<T> Json<T> {
45    pub fn into_inner(self) -> T {
46        self.0
47    }
48}
49
50impl<'de, T> Deserialize<'de> for Json<T>
51where
52    T: Deserialize<'de>,
53{
54    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55    where
56        D: serde::Deserializer<'de>,
57    {
58        use std::{fmt, marker::PhantomData};
59
60        struct Visitor<T> {
61            phantom: PhantomData<T>,
62        }
63
64        impl<'de, T> de::Visitor<'de> for Visitor<T>
65        where
66            T: Deserialize<'de>,
67        {
68            type Value = Json<T>;
69
70            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
71                formatter.write_str("Json")
72            }
73
74            fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
75            where
76                E: de::Error,
77            {
78                let value: T = serde_json::from_slice(v).map_err(|e| {
79                    de::Error::custom(format!(
80                        "Cannot deserialize from json (borrowed bytes): {}",
81                        e
82                    ))
83                })?;
84                Ok(Json(value))
85            }
86
87            fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
88            where
89                E: de::Error,
90            {
91                let value: T = serde_json::from_str(v).map_err(|e| {
92                    de::Error::custom(format!(
93                        "Cannot deserialize from json (borrowed str): {}",
94                        e
95                    ))
96                })?;
97                Ok(Json(value))
98            }
99        }
100
101        deserializer.deserialize_any(Visitor {
102            phantom: PhantomData,
103        })
104    }
105}
106
107/// Wrapper type that serializes a Rust value as JSON before sending it to Redis.
108///
109/// This is useful for storing structured data in Redis as a bulk string using JSON encoding.
110/// Typically used with commands like `SET`, `HSET`, or any command that takes a bulk string.
111///
112/// # Example
113/// ```rust
114/// use rustis::{
115///     client::Client,
116///     commands::{FlushingMode, ServerCommands, StringCommands},
117///     resp::{Json, JsonRef},
118///     Result
119/// };
120///
121/// #[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
122/// struct User {
123///     id: u32,
124///     name: String,
125/// }
126///
127/// #[cfg_attr(feature = "tokio-runtime", tokio::main)]
128/// #[cfg_attr(feature = "async-std-runtime", async_std::main)]
129/// async fn main() -> Result<()> {
130///     let client = Client::connect("127.0.0.1:6379").await?;
131///     client.flushall(FlushingMode::Sync).await?;
132///     let user1 = User { id: 12, name: "foo".to_string() };
133///     client.set("user:123", JsonRef(&user1)).await;
134///     let Json(user2): Json<User> = client.get("user:123").await?;
135///
136///     assert_eq!(user1, user2);
137///     Ok(())
138/// }
139/// ```
140#[derive(Debug, Clone)]
141#[must_use]
142pub struct JsonRef<'a, T>(pub &'a T);
143
144impl<'a, T> Serialize for JsonRef<'a, T>
145where
146    T: Serialize,
147{
148    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
149    where
150        S: serde::Serializer,
151    {
152        if let Ok(bytes) = serde_json::to_vec(&self.0) {
153            serializer.serialize_bytes(&bytes)
154        } else {
155            serializer.serialize_unit()
156        }
157    }
158}