jsonpath_lib/
lib.rs

1//! JsonPath implementation written in Rust.
2//!
3//! # Example
4//! ```
5//! extern crate jsonpath_lib as jsonpath;
6//! #[macro_use] extern crate serde_json;
7//! let json_obj = json!({
8//!     "store": {
9//!         "book": [
10//!             {
11//!                 "category": "reference",
12//!                 "author": "Nigel Rees",
13//!                 "title": "Sayings of the Century",
14//!                 "price": 8.95
15//!             },
16//!             {
17//!                 "category": "fiction",
18//!                 "author": "Evelyn Waugh",
19//!                 "title": "Sword of Honour",
20//!                 "price": 12.99
21//!             },
22//!             {
23//!                 "category": "fiction",
24//!                 "author": "Herman Melville",
25//!                 "title": "Moby Dick",
26//!                 "isbn": "0-553-21311-3",
27//!                 "price": 8.99
28//!             },
29//!             {
30//!                 "category": "fiction",
31//!                 "author": "J. R. R. Tolkien",
32//!                 "title": "The Lord of the Rings",
33//!                 "isbn": "0-395-19395-8",
34//!                 "price": 22.99
35//!             }
36//!         ],
37//!         "bicycle": {
38//!             "color": "red",
39//!             "price": 19.95
40//!         }
41//!     },
42//!     "expensive": 10
43//! });
44//!
45//! let mut selector = jsonpath::selector(&json_obj);
46//!
47//! assert_eq!(selector("$.store.book[*].author").unwrap(),
48//!             vec![
49//!                 "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"
50//!             ]);
51//!
52//! assert_eq!(selector("$..author").unwrap(),
53//!             vec![
54//!                 "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"
55//!             ]);
56//!
57//! assert_eq!(selector("$.store.*").unwrap(),
58//!             vec![
59//!                 &json!([
60//!                     { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 },
61//!                     { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 },
62//!                     { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 },
63//!                     { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 }
64//!                 ]),
65//!                 &json!({ "color": "red", "price": 19.95 })
66//!             ]);
67//!
68//! assert_eq!(selector("$.store..price").unwrap(),
69//!             vec![
70//!                 8.95, 12.99, 8.99, 22.99, 19.95
71//!             ]);
72//!
73//! assert_eq!(selector("$..book[2]").unwrap(),
74//!             vec![
75//!                 &json!({
76//!                     "category" : "fiction",
77//!                     "author" : "Herman Melville",
78//!                     "title" : "Moby Dick",
79//!                     "isbn" : "0-553-21311-3",
80//!                     "price" : 8.99
81//!                 })
82//!             ]);
83//!
84//! assert_eq!(selector("$..book[-2]").unwrap(),
85//!             vec![
86//!                 &json!({
87//!                     "category" : "fiction",
88//!                     "author" : "Herman Melville",
89//!                     "title" : "Moby Dick",
90//!                     "isbn" : "0-553-21311-3",
91//!                     "price" : 8.99
92//!                 })
93//!             ]);
94//!
95//! assert_eq!(selector("$..book[0,1]").unwrap(),
96//!             vec![
97//!                 &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
98//!                 &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99})
99//!             ]);
100//!
101//! assert_eq!(selector("$..book[:2]").unwrap(),
102//!             vec![
103//!                 &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
104//!                 &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99})
105//!             ]);
106//!
107//! assert_eq!(selector("$..book[:2]").unwrap(),
108//!             vec![
109//!                 &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
110//!                 &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99})
111//!             ]);
112//!
113//! assert_eq!(selector("$..book[?(@.isbn)]").unwrap(),
114//!             vec![
115//!                 &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}),
116//!                 &json!({"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99})
117//!             ]);
118//!
119//! assert_eq!(selector("$.store.book[?(@.price < 10)]").unwrap(),
120//!             vec![
121//!                 &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
122//!                 &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99})
123//!             ]);
124//! ```
125#[macro_use]
126extern crate core;
127#[cfg(feature = "logs")]
128extern crate log;
129extern crate serde;
130extern crate serde_json;
131
132use serde_json::Value;
133
134#[allow(deprecated)]
135use parser::Node;
136#[allow(deprecated)]
137pub use parser::Parser;
138#[allow(deprecated)]
139pub use select::{Selector, SelectorMut};
140
141#[deprecated(since = "0.4.0", note = "It will be move to common module. since 0.5")]
142pub use select::JsonPathError;
143
144pub use paths::PathParser;
145pub use selector::{JsonSelector, JsonSelectorMut};
146use std::rc::Rc;
147
148#[cfg(feature = "ffi")]
149#[doc(hidden)]
150#[deprecated(
151    since = "0.4.0",
152    note = "'ffi' is moved to another location like 'wasm' from version 0.5.x"
153)]
154mod ffi;
155#[doc(hidden)]
156mod parser;
157#[doc(hidden)]
158mod select;
159
160mod paths;
161mod selector;
162
163#[macro_export]
164macro_rules! debug {
165    ($($arg:tt)*) => {
166        #[cfg(feature = "logs")]
167        {
168            log::debug!($($arg)*);
169        }
170    }
171}
172
173#[macro_export]
174macro_rules! trace {
175    ($($arg:tt)*) => {
176        #[cfg(feature = "logs")]
177        {
178            log::trace!($($arg)*);
179        }
180    }
181}
182
183impl From<&paths::TokenError> for JsonPathError {
184    fn from(e: &paths::TokenError) -> Self {
185        match e {
186            paths::TokenError::Eof => JsonPathError::Path("Eof".to_string()),
187            paths::TokenError::Position(pos) => {
188                JsonPathError::Path(["Position:", &pos.to_string()].concat())
189            }
190        }
191    }
192}
193
194/// It is a high-order function. it compile a jsonpath and then returns a closure that has JSON as argument. if you need to reuse a jsonpath, it is good for performance.
195///
196/// ```rust
197/// extern crate jsonpath_lib as jsonpath;
198/// #[macro_use] extern crate serde_json;
199///
200/// let mut first_firend = jsonpath::compile("$..friends[0]");
201///
202/// let json_obj = json!({
203///     "school": {
204///         "friends": [
205///             {"name": "친구1", "age": 20},
206///             {"name": "친구2", "age": 20}
207///         ]
208///     },
209///     "friends": [
210///         {"name": "친구3", "age": 30},
211///         {"name": "친구4"}
212/// ]});
213///
214/// let json = first_firend(&json_obj).unwrap();
215///
216/// assert_eq!(json, vec![
217///     &json!({"name": "친구3", "age": 30}),
218///     &json!({"name": "친구1", "age": 20})
219/// ]);
220/// ```
221#[deprecated(
222    since = "0.2.5",
223    note = "Please use the PathCompiled::compile function instead. It will be removed from 0.4.1"
224)]
225pub fn compile(path: &str) -> impl FnMut(&Value) -> Result<Vec<&Value>, JsonPathError> {
226    #[allow(deprecated)]
227    let node = parser::Parser::compile(path);
228    move |json| match &node {
229        Ok(node) => {
230            #[allow(deprecated)]
231            let mut selector = Selector::default();
232            selector.compiled_path(node).value(json).select()
233        }
234        Err(e) => Err(JsonPathError::Path(e.to_string())),
235    }
236}
237
238/// It is a high-order function. it returns a closure that has a jsonpath string as argument. you can use diffenent jsonpath for one JSON object.
239///
240/// ```rust
241/// extern crate jsonpath_lib as jsonpath;
242/// #[macro_use] extern crate serde_json;
243///
244/// let json_obj = json!({
245///     "school": {
246///         "friends": [
247///             {"name": "친구1", "age": 20},
248///             {"name": "친구2", "age": 20}
249///         ]
250///     },
251///     "friends": [
252///         {"name": "친구3", "age": 30},
253///         {"name": "친구4"}
254/// ]});
255///
256/// let mut selector = jsonpath::selector(&json_obj);
257///
258/// let json = selector("$..friends[0]").unwrap();
259///
260/// assert_eq!(json, vec![
261///     &json!({"name": "친구3", "age": 30}),
262///     &json!({"name": "친구1", "age": 20})
263/// ]);
264///
265/// let json = selector("$..friends[1]").unwrap();
266///
267/// assert_eq!(json, vec![
268///     &json!({"name": "친구4"}),
269///     &json!({"name": "친구2", "age": 20})
270/// ]);
271/// ```
272pub fn selector<'a>(
273    json: &'a Value,
274) -> impl FnMut(&'a str) -> Result<Vec<&'a Value>, JsonPathError> {
275    let mut selector = JsonSelector::default();
276    move |path| {
277        let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
278        selector
279            .reset_parser(parser)
280            .value(json)
281            .reset_value()
282            .select()
283    }
284}
285
286/// It is the same to `selector` function. but it deserialize the result as given type `T`.
287///
288/// ```rust
289/// extern crate jsonpath_lib as jsonpath;
290/// extern crate serde;
291/// #[macro_use] extern crate serde_json;
292///
293/// use serde::{Deserialize, Serialize};
294///
295/// let json_obj = json!({
296///     "school": {
297///         "friends": [
298///             {"name": "친구1", "age": 20},
299///             {"name": "친구2", "age": 20}
300///         ]
301///     },
302///     "friends": [
303///         {"name": "친구3", "age": 30},
304///         {"name": "친구4"}
305/// ]});
306///
307/// #[derive(Deserialize, PartialEq, Debug)]
308/// struct Friend {
309///     name: String,
310///     age: Option<u8>,
311/// }
312///
313/// let mut selector = jsonpath::selector_as::<Friend>(&json_obj);
314///
315/// let json = selector("$..friends[0]").unwrap();
316///
317/// let ret = vec!(
318///     Friend { name: "친구3".to_string(), age: Some(30) },
319///     Friend { name: "친구1".to_string(), age: Some(20) }
320/// );
321/// assert_eq!(json, ret);
322///
323/// let json = selector("$..friends[1]").unwrap();
324///
325/// let ret = vec!(
326///     Friend { name: "친구4".to_string(), age: None },
327///     Friend { name: "친구2".to_string(), age: Some(20) }
328/// );
329///
330/// assert_eq!(json, ret);
331/// ```
332pub fn selector_as<'a, T: serde::de::DeserializeOwned>(
333    json: &'a Value,
334) -> impl FnMut(&'a str) -> Result<Vec<T>, JsonPathError> + 'a {
335    let mut selector = JsonSelector::default();
336    let _ = selector.value(json);
337    move |path: &str| {
338        let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
339        selector.reset_parser(parser).reset_value().select_as()
340    }
341}
342
343/// It is a simple select function. but it compile the jsonpath argument every time.
344///
345/// ```rust
346/// extern crate jsonpath_lib as jsonpath;
347/// #[macro_use] extern crate serde_json;
348///
349/// let json_obj = json!({
350///     "school": {
351///         "friends": [
352///             {"name": "친구1", "age": 20},
353///             {"name": "친구2", "age": 20}
354///         ]
355///     },
356///     "friends": [
357///         {"name": "친구3", "age": 30},
358///         {"name": "친구4"}
359/// ]});
360///
361/// let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap();
362///
363/// assert_eq!(json, vec![
364///     &json!({"name": "친구3", "age": 30}),
365///     &json!({"name": "친구1", "age": 20})
366/// ]);
367/// ```
368pub fn select<'a>(json: &'a Value, path: &'a str) -> Result<Vec<&'a Value>, JsonPathError> {
369    let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
370    JsonSelector::new(parser).value(json).select()
371}
372
373/// It is the same to `select` function but it return the result as string.
374///
375/// ```rust
376/// extern crate jsonpath_lib as jsonpath;
377/// #[macro_use] extern crate serde_json;
378///
379/// let ret = jsonpath::select_as_str(r#"
380/// {
381///     "school": {
382///         "friends": [
383///                 {"name": "친구1", "age": 20},
384///                 {"name": "친구2", "age": 20}
385///             ]
386///     },
387///     "friends": [
388///         {"name": "친구3", "age": 30},
389///         {"name": "친구4"}
390///     ]
391/// }
392/// "#, "$..friends[0]").unwrap();
393///
394/// assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
395/// ```
396pub fn select_as_str(json_str: &str, path: &str) -> Result<String, JsonPathError> {
397    let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?;
398    let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
399    let ret = JsonSelector::new(parser).value(&json).select()?;
400    serde_json::to_string(&ret).map_err(|e| JsonPathError::Serde(e.to_string()))
401}
402
403/// It is the same to `select` function but it deserialize the the result as given type `T`.
404///
405/// ```rust
406/// extern crate jsonpath_lib as jsonpath;
407/// extern crate serde;
408/// #[macro_use] extern crate serde_json;
409///
410/// use serde::{Deserialize, Serialize};
411///
412/// #[derive(Deserialize, PartialEq, Debug)]
413/// struct Person {
414///     name: String,
415///     age: u8,
416///     phones: Vec<String>,
417/// }
418///
419/// let ret: Vec<Person> = jsonpath::select_as(r#"
420/// {
421///     "person":
422///         {
423///             "name": "Doe John",
424///             "age": 44,
425///             "phones": [
426///                 "+44 1234567",
427///                 "+44 2345678"
428///             ]
429///         }
430/// }
431/// "#, "$.person").unwrap();
432///
433/// let person = Person {
434///     name: "Doe John".to_string(),
435///     age: 44,
436///     phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
437/// };
438///
439/// assert_eq!(ret[0], person);
440/// ```
441pub fn select_as<T: serde::de::DeserializeOwned>(
442    json_str: &str,
443    path: &str,
444) -> Result<Vec<T>, JsonPathError> {
445    let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?;
446    let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
447    JsonSelector::new(parser).value(&json).select_as()
448}
449
450/// Delete(= replace with null) the JSON property using the jsonpath.
451///
452/// ```rust
453/// extern crate jsonpath_lib as jsonpath;
454/// #[macro_use] extern crate serde_json;
455///
456/// let json_obj = json!({
457///     "school": {
458///         "friends": [
459///             {"name": "친구1", "age": 20},
460///             {"name": "친구2", "age": 20}
461///         ]
462///     },
463///     "friends": [
464///         {"name": "친구3", "age": 30},
465///         {"name": "친구4"}
466/// ]});
467///
468/// let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]").unwrap();
469///
470/// assert_eq!(ret, json!({
471///     "school": {
472///         "friends": [
473///             null,
474///             null
475///         ]
476///     },
477///     "friends": [
478///         {"name": "친구3", "age": 30},
479///         {"name": "친구4"}
480/// ]}));
481/// ```
482pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> {
483    let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
484    let mut selector = JsonSelectorMut::new(parser);
485    let value = selector.value(value).delete()?;
486    Ok(value.take().unwrap_or(Value::Null))
487}
488
489/// Select JSON properties using a jsonpath and transform the result and then replace it. via closure that implements `FnMut` you can transform the selected results.
490///
491/// ```rust
492/// extern crate jsonpath_lib as jsonpath;
493/// #[macro_use] extern crate serde_json;
494///
495/// use serde_json::Value;
496///
497/// let json_obj = json!({
498///     "school": {
499///         "friends": [
500///             {"name": "친구1", "age": 20},
501///             {"name": "친구2", "age": 20}
502///         ]
503///     },
504///     "friends": [
505///         {"name": "친구3", "age": 30},
506///         {"name": "친구4"}
507/// ]});
508///
509/// let ret = jsonpath::replace_with(json_obj, "$..[?(@.age == 20)].age", &mut |v| {
510///     let age = if let Value::Number(n) = v {
511///         n.as_u64().unwrap() * 2
512///     } else {
513///         0
514///     };
515///
516///     Some(json!(age))
517/// }).unwrap();
518///
519/// assert_eq!(ret, json!({
520///     "school": {
521///         "friends": [
522///             {"name": "친구1", "age": 40},
523///             {"name": "친구2", "age": 40}
524///         ]
525///     },
526///     "friends": [
527///         {"name": "친구3", "age": 30},
528///         {"name": "친구4"}
529/// ]}));
530/// ```
531pub fn replace_with<F>(value: Value, path: &str, fun: &mut F) -> Result<Value, JsonPathError>
532where
533    F: FnMut(Value) -> Option<Value>,
534{
535    let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
536    let mut selector = JsonSelectorMut::new(parser);
537    let value = selector.value(value).replace_with(fun)?;
538    Ok(value.take().unwrap_or(Value::Null))
539}
540
541/// A pre-compiled expression.
542///
543/// Calling the select function of this struct will re-use the existing, compiled expression.
544///
545/// ## Example
546///
547/// ```rust
548/// extern crate jsonpath_lib as jsonpath;
549/// #[macro_use] extern crate serde_json;
550///
551/// let mut first_friend = jsonpath::Compiled::compile("$..friends[0]").unwrap();
552///
553/// let json_obj = json!({
554///     "school": {
555///         "friends": [
556///             {"name": "친구1", "age": 20},
557///             {"name": "친구2", "age": 20}
558///         ]
559///     },
560///     "friends": [
561///         {"name": "친구3", "age": 30},
562///         {"name": "친구4"}
563/// ]});
564///
565/// // call a first time
566///
567/// let json = first_friend.select(&json_obj).unwrap();
568///
569/// assert_eq!(json, vec![
570///     &json!({"name": "친구3", "age": 30}),
571///     &json!({"name": "친구1", "age": 20})
572/// ]);
573///
574/// // call a second time
575///
576/// let json = first_friend.select(&json_obj).unwrap();
577///
578/// assert_eq!(json, vec![
579///     &json!({"name": "친구3", "age": 30}),
580///     &json!({"name": "친구1", "age": 20})
581/// ]);
582/// ```
583#[derive(Clone, Debug)]
584#[deprecated(since = "0.4.0", note = "Please use PathCompiled.")]
585pub struct Compiled {
586    #[allow(deprecated)]
587    node: Node,
588}
589
590#[allow(deprecated)]
591impl Compiled {
592    /// Compile a path expression and return a compiled instance.
593    ///
594    /// If parsing the path fails, it will return an error.
595    pub fn compile(path: &str) -> Result<Self, String> {
596        let node = parser::Parser::compile(path)?;
597        Ok(Self { node })
598    }
599
600    /// Execute the select operation on the pre-compiled path.
601    pub fn select<'a>(&self, value: &'a Value) -> Result<Vec<&'a Value>, JsonPathError> {
602        let mut selector = Selector::default();
603        selector.compiled_path(&self.node).value(value).select()
604    }
605}
606
607/// A pre-compiled expression.
608///
609/// Calling the select function of this struct will re-use the existing, compiled expression.
610///
611/// ## Example
612///
613/// ```rust
614/// extern crate jsonpath_lib as jsonpath;
615/// #[macro_use] extern crate serde_json;
616///
617/// let mut first_friend = jsonpath::PathCompiled::compile("$..friends[0]").unwrap();
618///
619/// let json_obj = json!({
620///     "school": {
621///         "friends": [
622///             {"name": "친구1", "age": 20},
623///             {"name": "친구2", "age": 20}
624///         ]
625///     },
626///     "friends": [
627///         {"name": "친구3", "age": 30},
628///         {"name": "친구4"}
629/// ]});
630///
631/// // call a first time
632///
633/// let json = first_friend.select(&json_obj).unwrap();
634///
635/// assert_eq!(json, vec![
636///     &json!({"name": "친구3", "age": 30}),
637///     &json!({"name": "친구1", "age": 20})
638/// ]);
639///
640/// // call a second time
641///
642/// let json = first_friend.select(&json_obj).unwrap();
643///
644/// assert_eq!(json, vec![
645///     &json!({"name": "친구3", "age": 30}),
646///     &json!({"name": "친구1", "age": 20})
647/// ]);
648/// ```
649#[derive(Clone, Debug)]
650pub struct PathCompiled<'a> {
651    parser: Rc<PathParser<'a>>,
652}
653
654impl<'a> PathCompiled<'a> {
655    /// Compile a path expression and return a compiled instance.
656    ///
657    /// If parsing the path fails, it will return an error.
658    pub fn compile(path: &str) -> Result<PathCompiled, JsonPathError> {
659        let parser = PathParser::compile(path).map_err(|e| JsonPathError::from(&e))?;
660        Ok(PathCompiled {
661            parser: Rc::new(parser),
662        })
663    }
664
665    /// Execute the select operation on the pre-compiled path.
666    pub fn select(&self, value: &'a Value) -> Result<Vec<&'a Value>, JsonPathError> {
667        let mut selector = JsonSelector::new_ref(Rc::clone(&self.parser));
668        selector.value(value).select()
669    }
670}