1#![forbid(unsafe_code)]
4#![warn(
5 missing_docs,
6 elided_lifetimes_in_paths,
7 explicit_outlives_requirements,
8 missing_abi,
9 noop_method_call,
10 pointer_structural_match,
11 semicolon_in_expressions_from_macros,
12 unused_import_braces,
13 unused_lifetimes,
14 clippy::cargo,
15 clippy::missing_panics_doc,
16 clippy::doc_markdown,
17 clippy::ptr_as_ptr,
18 clippy::cloned_instead_of_copied,
19 clippy::unreadable_literal,
20 clippy::must_use_candidate
21)]
22#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
23
24use serde_json::Value;
25
26use ast::Span;
27use error::{ParseError, ParseOrJsonError};
28use eval::EvalCtx;
29use idx::{Idx, IdxPath};
30use utils::{delete_paths, replace_paths, try_replace_paths};
31
32pub mod ast;
33pub mod error;
34mod eval;
35pub mod idx;
36mod utils;
37
38#[doc(inline)]
39pub use ast::Path as JsonPath;
40
41pub fn find<'a>(pattern: &str, value: &'a Value) -> Result<Vec<&'a Value>, ParseError> {
48 Ok(JsonPath::compile(pattern)?.find(value))
49}
50
51pub fn find_str(pattern: &str, value: &str) -> Result<Vec<Value>, ParseOrJsonError> {
59 Ok(JsonPath::compile(pattern)?.find_str(value)?)
60}
61
62impl JsonPath {
63 pub fn compile(pattern: &str) -> Result<JsonPath, ParseError> {
69 use chumsky::{Parser, Stream};
70
71 let len = pattern.chars().count();
72 let stream = Stream::from_iter(
73 Span::from(len..len),
74 Box::new(
75 pattern
76 .chars()
77 .enumerate()
78 .map(|(i, c)| (c, Span::from(i..i + 1))),
79 ),
80 );
81
82 Self::parser()
83 .parse(stream)
84 .map_err(|e| ParseError::new(pattern, e))
85 }
86
87 #[must_use = "this does not modify the path or provided value"]
89 pub fn find<'a>(&self, value: &'a Value) -> Vec<&'a Value> {
90 let mut ctx = EvalCtx::new(value);
91 if self.has_parent() {
92 ctx.prepopulate_parents();
93 }
94 self.eval(&mut ctx);
95 ctx.into_matched()
96 }
97
98 #[must_use = "this does not modify the path or provided value"]
101 pub fn find_paths(&self, value: &Value) -> Vec<IdxPath> {
102 let mut ctx = EvalCtx::new(value);
103 ctx.prepopulate_parents();
104 self.eval(&mut ctx);
105 ctx.paths_matched()
106 }
107
108 #[must_use = "this returns the new value, without modifying the original. To work in-place, \
111 use `delete_on`"]
112 pub fn delete(&self, value: &Value) -> Value {
113 let paths = self.find_paths(value);
114 let mut out = value.clone();
115 delete_paths(paths, &mut out);
116 out
117 }
118
119 pub fn delete_on(&self, value: &mut Value) {
121 let paths = self.find_paths(value);
122 delete_paths(paths, value);
123 }
124
125 #[must_use = "this returns the new value, without modifying the original. To work in-place, \
128 use `replace_on`"]
129 pub fn replace(&self, value: &Value, f: impl FnMut(&Value) -> Value) -> Value {
130 let paths = self.find_paths(value);
131 let mut out = value.clone();
132 replace_paths(paths, &mut out, f);
133 out
134 }
135
136 pub fn replace_on(&self, value: &mut Value, f: impl FnMut(&Value) -> Value) {
139 let paths = self.find_paths(value);
140 replace_paths(paths, value, f);
141 }
142
143 #[must_use = "this returns the new value, without modifying the original. To work in-place, \
147 use `try_replace_on`"]
148 pub fn try_replace(&self, value: &Value, f: impl FnMut(&Value) -> Option<Value>) -> Value {
149 let paths = self.find_paths(value);
150 let mut out = value.clone();
151 try_replace_paths(paths, &mut out, f);
152 out
153 }
154
155 pub fn try_replace_on(&self, value: &mut Value, f: impl FnMut(&Value) -> Option<Value>) {
159 let paths = self.find_paths(value);
160 try_replace_paths(paths, value, f);
161 }
162
163 pub fn find_str(&self, str: &str) -> Result<Vec<Value>, serde_json::Error> {
169 let val = serde_json::from_str(str)?;
170 Ok(self.find(&val).into_iter().cloned().collect())
171 }
172
173 pub fn delete_str(&self, str: &str) -> Result<Value, serde_json::Error> {
179 let val = serde_json::from_str(str)?;
180 Ok(self.delete(&val))
181 }
182
183 pub fn replace_str(
189 &self,
190 str: &str,
191 f: impl FnMut(&Value) -> Value,
192 ) -> Result<Value, serde_json::Error> {
193 let val = serde_json::from_str(str)?;
194 Ok(self.replace(&val, f))
195 }
196
197 pub fn try_replace_str(
203 &self,
204 str: &str,
205 f: impl FnMut(&Value) -> Option<Value>,
206 ) -> Result<Value, serde_json::Error> {
207 let val = serde_json::from_str(str)?;
208 Ok(self.try_replace(&val, f))
209 }
210}
211
212#[cfg(test)]
213mod tests;