summaryrefslogtreecommitdiffstats
path: root/vendor/jsonpath_lib/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/jsonpath_lib/src/lib.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/jsonpath_lib/src/lib.rs')
-rw-r--r--vendor/jsonpath_lib/src/lib.rs540
1 files changed, 540 insertions, 0 deletions
diff --git a/vendor/jsonpath_lib/src/lib.rs b/vendor/jsonpath_lib/src/lib.rs
new file mode 100644
index 000000000..55ac51943
--- /dev/null
+++ b/vendor/jsonpath_lib/src/lib.rs
@@ -0,0 +1,540 @@
+//! JsonPath implementation written in Rust.
+//!
+//! # Example
+//! ```
+//! extern crate jsonpath_lib as jsonpath;
+//! #[macro_use] extern crate serde_json;
+//! let json_obj = json!({
+//! "store": {
+//! "book": [
+//! {
+//! "category": "reference",
+//! "author": "Nigel Rees",
+//! "title": "Sayings of the Century",
+//! "price": 8.95
+//! },
+//! {
+//! "category": "fiction",
+//! "author": "Evelyn Waugh",
+//! "title": "Sword of Honour",
+//! "price": 12.99
+//! },
+//! {
+//! "category": "fiction",
+//! "author": "Herman Melville",
+//! "title": "Moby Dick",
+//! "isbn": "0-553-21311-3",
+//! "price": 8.99
+//! },
+//! {
+//! "category": "fiction",
+//! "author": "J. R. R. Tolkien",
+//! "title": "The Lord of the Rings",
+//! "isbn": "0-395-19395-8",
+//! "price": 22.99
+//! }
+//! ],
+//! "bicycle": {
+//! "color": "red",
+//! "price": 19.95
+//! }
+//! },
+//! "expensive": 10
+//! });
+//!
+//! let mut selector = jsonpath::selector(&json_obj);
+//!
+//! assert_eq!(selector("$.store.book[*].author").unwrap(),
+//! vec![
+//! "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"
+//! ]);
+//!
+//! assert_eq!(selector("$..author").unwrap(),
+//! vec![
+//! "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"
+//! ]);
+//!
+//! assert_eq!(selector("$.store.*").unwrap(),
+//! vec![
+//! &json!([
+//! { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 },
+//! { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 },
+//! { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 },
+//! { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 }
+//! ]),
+//! &json!({ "color": "red", "price": 19.95 })
+//! ]);
+//!
+//! assert_eq!(selector("$.store..price").unwrap(),
+//! vec![
+//! 8.95, 12.99, 8.99, 22.99, 19.95
+//! ]);
+//!
+//! assert_eq!(selector("$..book[2]").unwrap(),
+//! vec![
+//! &json!({
+//! "category" : "fiction",
+//! "author" : "Herman Melville",
+//! "title" : "Moby Dick",
+//! "isbn" : "0-553-21311-3",
+//! "price" : 8.99
+//! })
+//! ]);
+//!
+//! assert_eq!(selector("$..book[-2]").unwrap(),
+//! vec![
+//! &json!({
+//! "category" : "fiction",
+//! "author" : "Herman Melville",
+//! "title" : "Moby Dick",
+//! "isbn" : "0-553-21311-3",
+//! "price" : 8.99
+//! })
+//! ]);
+//!
+//! assert_eq!(selector("$..book[0,1]").unwrap(),
+//! vec![
+//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
+//! &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99})
+//! ]);
+//!
+//! assert_eq!(selector("$..book[:2]").unwrap(),
+//! vec![
+//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
+//! &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99})
+//! ]);
+//!
+//! assert_eq!(selector("$..book[:2]").unwrap(),
+//! vec![
+//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
+//! &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99})
+//! ]);
+//!
+//! assert_eq!(selector("$..book[?(@.isbn)]").unwrap(),
+//! vec![
+//! &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}),
+//! &json!({"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99})
+//! ]);
+//!
+//! assert_eq!(selector("$.store.book[?(@.price < 10)]").unwrap(),
+//! vec![
+//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}),
+//! &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99})
+//! ]);
+//! ```
+extern crate array_tool;
+extern crate core;
+extern crate env_logger;
+#[macro_use]
+extern crate log;
+extern crate serde;
+extern crate serde_json;
+
+use serde_json::Value;
+
+pub use parser::Parser; // TODO private
+pub use select::JsonPathError;
+pub use select::{Selector, SelectorMut};
+use parser::Node;
+
+#[doc(hidden)]
+mod ffi;
+#[doc(hidden)]
+mod parser;
+#[doc(hidden)]
+mod select;
+
+/// 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.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// let mut first_firend = jsonpath::compile("$..friends[0]");
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// let json = first_firend(&json_obj).unwrap();
+///
+/// assert_eq!(json, vec![
+/// &json!({"name": "친구3", "age": 30}),
+/// &json!({"name": "친구1", "age": 20})
+/// ]);
+/// ```
+#[deprecated(
+ since = "0.2.5",
+ note = "Please use the Compiled::compile function instead"
+)]
+pub fn compile(path: &str) -> impl FnMut(&Value) -> Result<Vec<&Value>, JsonPathError> {
+ let node = parser::Parser::compile(path);
+ move |json| match &node {
+ Ok(node) => {
+ let mut selector = Selector::default();
+ selector.compiled_path(node).value(json).select()
+ }
+ Err(e) => Err(JsonPathError::Path(e.to_string())),
+ }
+}
+
+/// 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.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// let mut selector = jsonpath::selector(&json_obj);
+///
+/// let json = selector("$..friends[0]").unwrap();
+///
+/// assert_eq!(json, vec![
+/// &json!({"name": "친구3", "age": 30}),
+/// &json!({"name": "친구1", "age": 20})
+/// ]);
+///
+/// let json = selector("$..friends[1]").unwrap();
+///
+/// assert_eq!(json, vec![
+/// &json!({"name": "친구4"}),
+/// &json!({"name": "친구2", "age": 20})
+/// ]);
+/// ```
+#[allow(clippy::needless_lifetimes)]
+pub fn selector<'a>(json: &'a Value) -> impl FnMut(&str) -> Result<Vec<&'a Value>, JsonPathError> {
+ let mut selector = Selector::default();
+ let _ = selector.value(json);
+ move |path: &str| selector.str_path(path)?.reset_value().select()
+}
+
+/// It is the same to `selector` function. but it deserialize the result as given type `T`.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// extern crate serde;
+/// #[macro_use] extern crate serde_json;
+///
+/// use serde::{Deserialize, Serialize};
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// #[derive(Deserialize, PartialEq, Debug)]
+/// struct Friend {
+/// name: String,
+/// age: Option<u8>,
+/// }
+///
+/// let mut selector = jsonpath::selector_as::<Friend>(&json_obj);
+///
+/// let json = selector("$..friends[0]").unwrap();
+///
+/// let ret = vec!(
+/// Friend { name: "친구3".to_string(), age: Some(30) },
+/// Friend { name: "친구1".to_string(), age: Some(20) }
+/// );
+/// assert_eq!(json, ret);
+///
+/// let json = selector("$..friends[1]").unwrap();
+///
+/// let ret = vec!(
+/// Friend { name: "친구4".to_string(), age: None },
+/// Friend { name: "친구2".to_string(), age: Some(20) }
+/// );
+///
+/// assert_eq!(json, ret);
+/// ```
+pub fn selector_as<T: serde::de::DeserializeOwned>(
+ json: &Value,
+) -> impl FnMut(&str) -> Result<Vec<T>, JsonPathError> + '_ {
+ let mut selector = Selector::default();
+ let _ = selector.value(json);
+ move |path: &str| selector.str_path(path)?.reset_value().select_as()
+}
+
+/// It is a simple select function. but it compile the jsonpath argument every time.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap();
+///
+/// assert_eq!(json, vec![
+/// &json!({"name": "친구3", "age": 30}),
+/// &json!({"name": "친구1", "age": 20})
+/// ]);
+/// ```
+pub fn select<'a>(json: &'a Value, path: &str) -> Result<Vec<&'a Value>, JsonPathError> {
+ Selector::default().str_path(path)?.value(json).select()
+}
+
+/// It is the same to `select` function but it return the result as string.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// let ret = jsonpath::select_as_str(r#"
+/// {
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]
+/// }
+/// "#, "$..friends[0]").unwrap();
+///
+/// assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
+/// ```
+pub fn select_as_str(json_str: &str, path: &str) -> Result<String, JsonPathError> {
+ let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?;
+ let ret = Selector::default().str_path(path)?.value(&json).select()?;
+ serde_json::to_string(&ret).map_err(|e| JsonPathError::Serde(e.to_string()))
+}
+
+/// It is the same to `select` function but it deserialize the the result as given type `T`.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// extern crate serde;
+/// #[macro_use] extern crate serde_json;
+///
+/// use serde::{Deserialize, Serialize};
+///
+/// #[derive(Deserialize, PartialEq, Debug)]
+/// struct Person {
+/// name: String,
+/// age: u8,
+/// phones: Vec<String>,
+/// }
+///
+/// let ret: Vec<Person> = jsonpath::select_as(r#"
+/// {
+/// "person":
+/// {
+/// "name": "Doe John",
+/// "age": 44,
+/// "phones": [
+/// "+44 1234567",
+/// "+44 2345678"
+/// ]
+/// }
+/// }
+/// "#, "$.person").unwrap();
+///
+/// let person = Person {
+/// name: "Doe John".to_string(),
+/// age: 44,
+/// phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
+/// };
+///
+/// assert_eq!(ret[0], person);
+/// ```
+pub fn select_as<T: serde::de::DeserializeOwned>(
+ json_str: &str,
+ path: &str,
+) -> Result<Vec<T>, JsonPathError> {
+ let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?;
+ Selector::default().str_path(path)?.value(&json).select_as()
+}
+
+/// Delete(= replace with null) the JSON property using the jsonpath.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]").unwrap();
+///
+/// assert_eq!(ret, json!({
+/// "school": {
+/// "friends": [
+/// null,
+/// null
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]}));
+/// ```
+pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> {
+ let mut selector = SelectorMut::default();
+ let value = selector.str_path(path)?.value(value).delete()?;
+ Ok(value.take().unwrap_or(Value::Null))
+}
+
+/// 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.
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// use serde_json::Value;
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// let ret = jsonpath::replace_with(json_obj, "$..[?(@.age == 20)].age", &mut |v| {
+/// let age = if let Value::Number(n) = v {
+/// n.as_u64().unwrap() * 2
+/// } else {
+/// 0
+/// };
+///
+/// Some(json!(age))
+/// }).unwrap();
+///
+/// assert_eq!(ret, json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 40},
+/// {"name": "친구2", "age": 40}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]}));
+/// ```
+pub fn replace_with<F>(value: Value, path: &str, fun: &mut F) -> Result<Value, JsonPathError>
+where
+ F: FnMut(Value) -> Option<Value>,
+{
+ let mut selector = SelectorMut::default();
+ let value = selector.str_path(path)?.value(value).replace_with(fun)?;
+ Ok(value.take().unwrap_or(Value::Null))
+}
+
+/// A pre-compiled expression.
+///
+/// Calling the select function of this struct will re-use the existing, compiled expression.
+///
+/// ## Example
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// let mut first_friend = jsonpath::Compiled::compile("$..friends[0]").unwrap();
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [
+/// {"name": "친구1", "age": 20},
+/// {"name": "친구2", "age": 20}
+/// ]
+/// },
+/// "friends": [
+/// {"name": "친구3", "age": 30},
+/// {"name": "친구4"}
+/// ]});
+///
+/// // call a first time
+///
+/// let json = first_friend.select(&json_obj).unwrap();
+///
+/// assert_eq!(json, vec![
+/// &json!({"name": "친구3", "age": 30}),
+/// &json!({"name": "친구1", "age": 20})
+/// ]);
+///
+/// // call a second time
+///
+/// let json = first_friend.select(&json_obj).unwrap();
+///
+/// assert_eq!(json, vec![
+/// &json!({"name": "친구3", "age": 30}),
+/// &json!({"name": "친구1", "age": 20})
+/// ]);
+/// ```
+#[derive(Clone, Debug)]
+pub struct Compiled {
+ node: Node,
+}
+
+impl Compiled {
+ /// Compile a path expression and return a compiled instance.
+ ///
+ /// If parsing the path fails, it will return an error.
+ pub fn compile(path: &str) -> Result<Compiled, String> {
+ let node = parser::Parser::compile(path)?;
+ Ok(Compiled{
+ node
+ })
+ }
+
+ /// Execute the select operation on the pre-compiled path.
+ pub fn select<'a>(&self, value: &'a Value) -> Result<Vec<&'a Value>, JsonPathError> {
+ let mut selector = Selector::default();
+ selector.compiled_path(&self.node).value(value).select()
+ }
+}