Skip to main content

glide/commands/
json.rs

1// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2//! JSON module commands (`JSON.*`). Mirrors Python's `glide_json` namespace.
3//!
4//! These require the `json` module to be loaded on the server. Paths default to
5//! the JSONPath root (`$`) where the server does.
6
7use crate::ValkeyResult;
8use crate::cmd::Cmd;
9use crate::executor::CommandExecutor;
10use crate::value::FromValkeyValue;
11use crate::value::ValkeyValue;
12use crate::write::ToValkeyArgs;
13use async_trait::async_trait;
14use bytes::Bytes;
15
16/// JSON module commands (`JSON.SET`, `JSON.GET`, `JSON.ARRAPPEND`, ...).
17///
18/// Mirrors the Python `glide_json` module functions.
19#[async_trait]
20pub trait JsonCommands: CommandExecutor {
21    /// Set the JSON value at `path` in `key` (`JSON.SET`).
22    async fn json_set<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send, V: ToValkeyArgs + Send>(
23        &self,
24        key: K,
25        path: P,
26        value: V,
27    ) -> ValkeyResult<()> {
28        let mut cmd = Cmd::new();
29        cmd.arg("JSON.SET").arg(key).arg(path).arg(value);
30        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
31    }
32
33    /// Get the JSON value(s) at `paths` in `key` (`JSON.GET`).
34    async fn json_get<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send + Sync>(
35        &self,
36        key: K,
37        paths: &[P],
38    ) -> ValkeyResult<Option<Bytes>> {
39        let mut cmd = Cmd::new();
40        cmd.arg("JSON.GET").arg(key);
41        for p in paths {
42            cmd.arg(p);
43        }
44        Option::<Bytes>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
45    }
46
47    /// Delete the value(s) at `path` (`JSON.DEL`); returns the number deleted.
48    async fn json_del<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
49        &self,
50        key: K,
51        path: P,
52    ) -> ValkeyResult<i64> {
53        let mut cmd = Cmd::new();
54        cmd.arg("JSON.DEL").arg(key).arg(path);
55        i64::from_owned_valkey_value(self.execute_command(cmd, None).await?)
56    }
57
58    /// Delete the value(s) at `path` (`JSON.FORGET`, an alias of `JSON.DEL`).
59    async fn json_forget<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
60        &self,
61        key: K,
62        path: P,
63    ) -> ValkeyResult<i64> {
64        let mut cmd = Cmd::new();
65        cmd.arg("JSON.FORGET").arg(key).arg(path);
66        i64::from_owned_valkey_value(self.execute_command(cmd, None).await?)
67    }
68
69    /// Get the type of the value(s) at `path` (`JSON.TYPE`).
70    async fn json_type<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
71        &self,
72        key: K,
73        path: P,
74    ) -> ValkeyResult<ValkeyValue> {
75        let mut cmd = Cmd::new();
76        cmd.arg("JSON.TYPE").arg(key).arg(path);
77        self.execute_command(cmd, None).await
78    }
79
80    /// Increment the number(s) at `path` by `value` (`JSON.NUMINCRBY`). Returns
81    /// the resulting value(s) encoded as a JSON string.
82    async fn json_numincrby<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
83        &self,
84        key: K,
85        path: P,
86        value: f64,
87    ) -> ValkeyResult<Option<Bytes>> {
88        let mut cmd = Cmd::new();
89        cmd.arg("JSON.NUMINCRBY").arg(key).arg(path).arg(value);
90        Option::<Bytes>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
91    }
92
93    /// Multiply the number(s) at `path` by `value` (`JSON.NUMMULTBY`).
94    async fn json_nummultby<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
95        &self,
96        key: K,
97        path: P,
98        value: f64,
99    ) -> ValkeyResult<Option<Bytes>> {
100        let mut cmd = Cmd::new();
101        cmd.arg("JSON.NUMMULTBY").arg(key).arg(path).arg(value);
102        Option::<Bytes>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
103    }
104
105    /// Append `value` to the string(s) at `path` (`JSON.STRAPPEND`). Returns the
106    /// new string length(s).
107    async fn json_strappend<
108        K: ToValkeyArgs + Send,
109        P: ToValkeyArgs + Send,
110        V: ToValkeyArgs + Send,
111    >(
112        &self,
113        key: K,
114        path: P,
115        value: V,
116    ) -> ValkeyResult<ValkeyValue> {
117        let mut cmd = Cmd::new();
118        cmd.arg("JSON.STRAPPEND").arg(key).arg(path).arg(value);
119        self.execute_command(cmd, None).await
120    }
121
122    /// Get the length of the string(s) at `path` (`JSON.STRLEN`).
123    async fn json_strlen<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
124        &self,
125        key: K,
126        path: P,
127    ) -> ValkeyResult<ValkeyValue> {
128        let mut cmd = Cmd::new();
129        cmd.arg("JSON.STRLEN").arg(key).arg(path);
130        self.execute_command(cmd, None).await
131    }
132
133    /// Append `values` to the array(s) at `path` (`JSON.ARRAPPEND`).
134    async fn json_arrappend<
135        K: ToValkeyArgs + Send,
136        P: ToValkeyArgs + Send,
137        V: ToValkeyArgs + Send + Sync,
138    >(
139        &self,
140        key: K,
141        path: P,
142        values: &[V],
143    ) -> ValkeyResult<ValkeyValue> {
144        let mut cmd = Cmd::new();
145        cmd.arg("JSON.ARRAPPEND").arg(key).arg(path);
146        for v in values {
147            cmd.arg(v);
148        }
149        self.execute_command(cmd, None).await
150    }
151
152    /// Insert `values` into the array(s) at `path` starting at `index`
153    /// (`JSON.ARRINSERT`).
154    async fn json_arrinsert<
155        K: ToValkeyArgs + Send,
156        P: ToValkeyArgs + Send,
157        V: ToValkeyArgs + Send + Sync,
158    >(
159        &self,
160        key: K,
161        path: P,
162        index: i64,
163        values: &[V],
164    ) -> ValkeyResult<ValkeyValue> {
165        let mut cmd = Cmd::new();
166        cmd.arg("JSON.ARRINSERT").arg(key).arg(path).arg(index);
167        for v in values {
168            cmd.arg(v);
169        }
170        self.execute_command(cmd, None).await
171    }
172
173    /// Get the length of the array(s) at `path` (`JSON.ARRLEN`).
174    async fn json_arrlen<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
175        &self,
176        key: K,
177        path: P,
178    ) -> ValkeyResult<ValkeyValue> {
179        let mut cmd = Cmd::new();
180        cmd.arg("JSON.ARRLEN").arg(key).arg(path);
181        self.execute_command(cmd, None).await
182    }
183
184    /// Pop an element from the array(s) at `path` at `index` (`JSON.ARRPOP`).
185    async fn json_arrpop<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
186        &self,
187        key: K,
188        path: P,
189        index: Option<i64>,
190    ) -> ValkeyResult<ValkeyValue> {
191        let mut cmd = Cmd::new();
192        cmd.arg("JSON.ARRPOP").arg(key).arg(path);
193        if let Some(i) = index {
194            cmd.arg(i);
195        }
196        self.execute_command(cmd, None).await
197    }
198
199    /// Trim the array(s) at `path` to the inclusive range `[start, stop]`
200    /// (`JSON.ARRTRIM`).
201    async fn json_arrtrim<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
202        &self,
203        key: K,
204        path: P,
205        start: i64,
206        stop: i64,
207    ) -> ValkeyResult<ValkeyValue> {
208        let mut cmd = Cmd::new();
209        cmd.arg("JSON.ARRTRIM")
210            .arg(key)
211            .arg(path)
212            .arg(start)
213            .arg(stop);
214        self.execute_command(cmd, None).await
215    }
216
217    /// Get the keys of the object(s) at `path` (`JSON.OBJKEYS`).
218    async fn json_objkeys<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
219        &self,
220        key: K,
221        path: P,
222    ) -> ValkeyResult<ValkeyValue> {
223        let mut cmd = Cmd::new();
224        cmd.arg("JSON.OBJKEYS").arg(key).arg(path);
225        self.execute_command(cmd, None).await
226    }
227
228    /// Get the number of keys in the object(s) at `path` (`JSON.OBJLEN`).
229    async fn json_objlen<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
230        &self,
231        key: K,
232        path: P,
233    ) -> ValkeyResult<ValkeyValue> {
234        let mut cmd = Cmd::new();
235        cmd.arg("JSON.OBJLEN").arg(key).arg(path);
236        self.execute_command(cmd, None).await
237    }
238
239    /// Toggle the boolean value(s) at `path` (`JSON.TOGGLE`).
240    async fn json_toggle<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
241        &self,
242        key: K,
243        path: P,
244    ) -> ValkeyResult<ValkeyValue> {
245        let mut cmd = Cmd::new();
246        cmd.arg("JSON.TOGGLE").arg(key).arg(path);
247        self.execute_command(cmd, None).await
248    }
249
250    /// Clear container value(s) at `path` (`JSON.CLEAR`); returns the number of
251    /// values cleared.
252    async fn json_clear<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
253        &self,
254        key: K,
255        path: P,
256    ) -> ValkeyResult<i64> {
257        let mut cmd = Cmd::new();
258        cmd.arg("JSON.CLEAR").arg(key).arg(path);
259        i64::from_owned_valkey_value(self.execute_command(cmd, None).await?)
260    }
261
262    /// Find the index of `value` in the array(s) at `path` (`JSON.ARRINDEX`).
263    /// Optionally restrict the search to `[start, end)`.
264    async fn json_arrindex<
265        K: ToValkeyArgs + Send,
266        P: ToValkeyArgs + Send,
267        V: ToValkeyArgs + Send,
268    >(
269        &self,
270        key: K,
271        path: P,
272        value: V,
273        range: Option<(i64, i64)>,
274    ) -> ValkeyResult<ValkeyValue> {
275        let mut cmd = Cmd::new();
276        cmd.arg("JSON.ARRINDEX").arg(key).arg(path).arg(value);
277        if let Some((start, end)) = range {
278            cmd.arg(start).arg(end);
279        }
280        self.execute_command(cmd, None).await
281    }
282
283    /// Get the value(s) at `path` from multiple keys (`JSON.MGET`).
284    async fn json_mget<K: ToValkeyArgs + Send + Sync, P: ToValkeyArgs + Send>(
285        &self,
286        keys: &[K],
287        path: P,
288    ) -> ValkeyResult<Vec<Option<Bytes>>> {
289        let mut cmd = Cmd::new();
290        cmd.arg("JSON.MGET");
291        for k in keys {
292            cmd.arg(k);
293        }
294        cmd.arg(path);
295        match self.execute_command(cmd, None).await? {
296            ValkeyValue::Array(items) => items
297                .into_iter()
298                .map(Option::<Bytes>::from_owned_valkey_value)
299                .collect(),
300            ValkeyValue::Nil => Ok(Vec::new()),
301            other => Ok(vec![Option::<Bytes>::from_owned_valkey_value(other)?]),
302        }
303    }
304
305    /// Get the value(s) at `path` in RESP form (`JSON.RESP`).
306    async fn json_resp<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
307        &self,
308        key: K,
309        path: P,
310    ) -> ValkeyResult<ValkeyValue> {
311        let mut cmd = Cmd::new();
312        cmd.arg("JSON.RESP").arg(key).arg(path);
313        self.execute_command(cmd, None).await
314    }
315
316    /// Report the memory usage of the value(s) at `path`
317    /// (`JSON.DEBUG MEMORY`).
318    async fn json_debug_memory<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
319        &self,
320        key: K,
321        path: P,
322    ) -> ValkeyResult<ValkeyValue> {
323        let mut cmd = Cmd::new();
324        cmd.arg("JSON.DEBUG").arg("MEMORY").arg(key).arg(path);
325        self.execute_command(cmd, None).await
326    }
327
328    /// Report the number of fields in the value(s) at `path`
329    /// (`JSON.DEBUG FIELDS`).
330    async fn json_debug_fields<K: ToValkeyArgs + Send, P: ToValkeyArgs + Send>(
331        &self,
332        key: K,
333        path: P,
334    ) -> ValkeyResult<ValkeyValue> {
335        let mut cmd = Cmd::new();
336        cmd.arg("JSON.DEBUG").arg("FIELDS").arg(key).arg(path);
337        self.execute_command(cmd, None).await
338    }
339}
340
341impl<T: CommandExecutor + ?Sized> JsonCommands for T {}