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 | extern crate core; |
126 | #[macro_use ] |
127 | extern crate log; |
128 | extern crate serde; |
129 | extern crate serde_json; |
130 | |
131 | use serde_json::Value; |
132 | |
133 | pub use parser::Parser; // TODO private |
134 | pub use select::JsonPathError; |
135 | pub use select::{Selector, SelectorMut}; |
136 | use parser::Node; |
137 | |
138 | #[doc (hidden)] |
139 | mod ffi; |
140 | #[doc (hidden)] |
141 | mod parser; |
142 | #[doc (hidden)] |
143 | mod select; |
144 | |
145 | /// 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. |
146 | /// |
147 | /// ```rust |
148 | /// extern crate jsonpath_lib as jsonpath; |
149 | /// #[macro_use] extern crate serde_json; |
150 | /// |
151 | /// let mut first_firend = jsonpath::compile("$..friends[0]" ); |
152 | /// |
153 | /// let json_obj = json!({ |
154 | /// "school" : { |
155 | /// "friends" : [ |
156 | /// {"name" : "친구1" , "age" : 20}, |
157 | /// {"name" : "친구2" , "age" : 20} |
158 | /// ] |
159 | /// }, |
160 | /// "friends" : [ |
161 | /// {"name" : "친구3" , "age" : 30}, |
162 | /// {"name" : "친구4" } |
163 | /// ]}); |
164 | /// |
165 | /// let json = first_firend(&json_obj).unwrap(); |
166 | /// |
167 | /// assert_eq!(json, vec![ |
168 | /// &json!({"name" : "친구3" , "age" : 30}), |
169 | /// &json!({"name" : "친구1" , "age" : 20}) |
170 | /// ]); |
171 | /// ``` |
172 | #[deprecated ( |
173 | since = "0.2.5" , |
174 | note = "Please use the Compiled::compile function instead" |
175 | )] |
176 | pub fn compile(path: &str) -> impl FnMut(&Value) -> Result<Vec<&Value>, JsonPathError> { |
177 | let node: Result = parser::Parser::compile(input:path); |
178 | move |json: &Value| match &node { |
179 | Ok(node: &Node) => { |
180 | let mut selector: Selector<'_, '_> = Selector::default(); |
181 | selector.compiled_path(node).value(json).select() |
182 | } |
183 | Err(e: &String) => Err(JsonPathError::Path(e.to_string())), |
184 | } |
185 | } |
186 | |
187 | /// 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. |
188 | /// |
189 | /// ```rust |
190 | /// extern crate jsonpath_lib as jsonpath; |
191 | /// #[macro_use] extern crate serde_json; |
192 | /// |
193 | /// let json_obj = json!({ |
194 | /// "school" : { |
195 | /// "friends" : [ |
196 | /// {"name" : "친구1" , "age" : 20}, |
197 | /// {"name" : "친구2" , "age" : 20} |
198 | /// ] |
199 | /// }, |
200 | /// "friends" : [ |
201 | /// {"name" : "친구3" , "age" : 30}, |
202 | /// {"name" : "친구4" } |
203 | /// ]}); |
204 | /// |
205 | /// let mut selector = jsonpath::selector(&json_obj); |
206 | /// |
207 | /// let json = selector("$..friends[0]" ).unwrap(); |
208 | /// |
209 | /// assert_eq!(json, vec![ |
210 | /// &json!({"name" : "친구3" , "age" : 30}), |
211 | /// &json!({"name" : "친구1" , "age" : 20}) |
212 | /// ]); |
213 | /// |
214 | /// let json = selector("$..friends[1]" ).unwrap(); |
215 | /// |
216 | /// assert_eq!(json, vec![ |
217 | /// &json!({"name" : "친구4" }), |
218 | /// &json!({"name" : "친구2" , "age" : 20}) |
219 | /// ]); |
220 | /// ``` |
221 | #[allow (clippy::needless_lifetimes)] |
222 | pub fn selector<'a>(json: &'a Value) -> impl FnMut(&str) -> Result<Vec<&'a Value>, JsonPathError> { |
223 | let mut selector: Selector<'_, '_> = Selector::default(); |
224 | let _ = selector.value(json); |
225 | move |path: &str| selector.str_path(path)?.reset_value().select() |
226 | } |
227 | |
228 | /// It is the same to `selector` function. but it deserialize the result as given type `T`. |
229 | /// |
230 | /// ```rust |
231 | /// extern crate jsonpath_lib as jsonpath; |
232 | /// extern crate serde; |
233 | /// #[macro_use] extern crate serde_json; |
234 | /// |
235 | /// use serde::{Deserialize, Serialize}; |
236 | /// |
237 | /// let json_obj = json!({ |
238 | /// "school" : { |
239 | /// "friends" : [ |
240 | /// {"name" : "친구1" , "age" : 20}, |
241 | /// {"name" : "친구2" , "age" : 20} |
242 | /// ] |
243 | /// }, |
244 | /// "friends" : [ |
245 | /// {"name" : "친구3" , "age" : 30}, |
246 | /// {"name" : "친구4" } |
247 | /// ]}); |
248 | /// |
249 | /// #[derive(Deserialize, PartialEq, Debug)] |
250 | /// struct Friend { |
251 | /// name: String, |
252 | /// age: Option<u8>, |
253 | /// } |
254 | /// |
255 | /// let mut selector = jsonpath::selector_as::<Friend>(&json_obj); |
256 | /// |
257 | /// let json = selector("$..friends[0]" ).unwrap(); |
258 | /// |
259 | /// let ret = vec!( |
260 | /// Friend { name: "친구3" .to_string(), age: Some(30) }, |
261 | /// Friend { name: "친구1" .to_string(), age: Some(20) } |
262 | /// ); |
263 | /// assert_eq!(json, ret); |
264 | /// |
265 | /// let json = selector("$..friends[1]" ).unwrap(); |
266 | /// |
267 | /// let ret = vec!( |
268 | /// Friend { name: "친구4" .to_string(), age: None }, |
269 | /// Friend { name: "친구2" .to_string(), age: Some(20) } |
270 | /// ); |
271 | /// |
272 | /// assert_eq!(json, ret); |
273 | /// ``` |
274 | pub fn selector_as<T: serde::de::DeserializeOwned>( |
275 | json: &Value, |
276 | ) -> impl FnMut(&str) -> Result<Vec<T>, JsonPathError> + '_ { |
277 | let mut selector: Selector<'_, '_> = Selector::default(); |
278 | let _ = selector.value(json); |
279 | move |path: &str| selector.str_path(path)?.reset_value().select_as() |
280 | } |
281 | |
282 | /// It is a simple select function. but it compile the jsonpath argument every time. |
283 | /// |
284 | /// ```rust |
285 | /// extern crate jsonpath_lib as jsonpath; |
286 | /// #[macro_use] extern crate serde_json; |
287 | /// |
288 | /// let json_obj = json!({ |
289 | /// "school" : { |
290 | /// "friends" : [ |
291 | /// {"name" : "친구1" , "age" : 20}, |
292 | /// {"name" : "친구2" , "age" : 20} |
293 | /// ] |
294 | /// }, |
295 | /// "friends" : [ |
296 | /// {"name" : "친구3" , "age" : 30}, |
297 | /// {"name" : "친구4" } |
298 | /// ]}); |
299 | /// |
300 | /// let json = jsonpath::select(&json_obj, "$..friends[0]" ).unwrap(); |
301 | /// |
302 | /// assert_eq!(json, vec![ |
303 | /// &json!({"name" : "친구3" , "age" : 30}), |
304 | /// &json!({"name" : "친구1" , "age" : 20}) |
305 | /// ]); |
306 | /// ``` |
307 | pub fn select<'a>(json: &'a Value, path: &str) -> Result<Vec<&'a Value>, JsonPathError> { |
308 | Selector::default().str_path(path)?.value(json).select() |
309 | } |
310 | |
311 | /// It is the same to `select` function but it return the result as string. |
312 | /// |
313 | /// ```rust |
314 | /// extern crate jsonpath_lib as jsonpath; |
315 | /// #[macro_use] extern crate serde_json; |
316 | /// |
317 | /// let ret = jsonpath::select_as_str(r#" |
318 | /// { |
319 | /// "school": { |
320 | /// "friends": [ |
321 | /// {"name": "친구1", "age": 20}, |
322 | /// {"name": "친구2", "age": 20} |
323 | /// ] |
324 | /// }, |
325 | /// "friends": [ |
326 | /// {"name": "친구3", "age": 30}, |
327 | /// {"name": "친구4"} |
328 | /// ] |
329 | /// } |
330 | /// "# , "$..friends[0]" ).unwrap(); |
331 | /// |
332 | /// assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"# ); |
333 | /// ``` |
334 | pub fn select_as_str(json_str: &str, path: &str) -> Result<String, JsonPathError> { |
335 | let json: Value = serde_json::from_str(json_str).map_err(|e: Error| JsonPathError::Serde(e.to_string()))?; |
336 | let ret: Vec<&Value> = Selector::default().str_path(path)?.value(&json).select()?; |
337 | serde_json::to_string(&ret).map_err(|e: Error| JsonPathError::Serde(e.to_string())) |
338 | } |
339 | |
340 | /// It is the same to `select` function but it deserialize the the result as given type `T`. |
341 | /// |
342 | /// ```rust |
343 | /// extern crate jsonpath_lib as jsonpath; |
344 | /// extern crate serde; |
345 | /// #[macro_use] extern crate serde_json; |
346 | /// |
347 | /// use serde::{Deserialize, Serialize}; |
348 | /// |
349 | /// #[derive(Deserialize, PartialEq, Debug)] |
350 | /// struct Person { |
351 | /// name: String, |
352 | /// age: u8, |
353 | /// phones: Vec<String>, |
354 | /// } |
355 | /// |
356 | /// let ret: Vec<Person> = jsonpath::select_as(r#" |
357 | /// { |
358 | /// "person": |
359 | /// { |
360 | /// "name": "Doe John", |
361 | /// "age": 44, |
362 | /// "phones": [ |
363 | /// "+44 1234567", |
364 | /// "+44 2345678" |
365 | /// ] |
366 | /// } |
367 | /// } |
368 | /// "# , "$.person" ).unwrap(); |
369 | /// |
370 | /// let person = Person { |
371 | /// name: "Doe John" .to_string(), |
372 | /// age: 44, |
373 | /// phones: vec!["+44 1234567" .to_string(), "+44 2345678" .to_string()], |
374 | /// }; |
375 | /// |
376 | /// assert_eq!(ret[0], person); |
377 | /// ``` |
378 | pub fn select_as<T: serde::de::DeserializeOwned>( |
379 | json_str: &str, |
380 | path: &str, |
381 | ) -> Result<Vec<T>, JsonPathError> { |
382 | let json: Value = serde_json::from_str(json_str).map_err(|e: Error| JsonPathError::Serde(e.to_string()))?; |
383 | Selector::default().str_path(path)?.value(&json).select_as() |
384 | } |
385 | |
386 | /// Delete(= replace with null) the JSON property using the jsonpath. |
387 | /// |
388 | /// ```rust |
389 | /// extern crate jsonpath_lib as jsonpath; |
390 | /// #[macro_use] extern crate serde_json; |
391 | /// |
392 | /// let json_obj = json!({ |
393 | /// "school" : { |
394 | /// "friends" : [ |
395 | /// {"name" : "친구1" , "age" : 20}, |
396 | /// {"name" : "친구2" , "age" : 20} |
397 | /// ] |
398 | /// }, |
399 | /// "friends" : [ |
400 | /// {"name" : "친구3" , "age" : 30}, |
401 | /// {"name" : "친구4" } |
402 | /// ]}); |
403 | /// |
404 | /// let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]" ).unwrap(); |
405 | /// |
406 | /// assert_eq!(ret, json!({ |
407 | /// "school" : { |
408 | /// "friends" : [ |
409 | /// null, |
410 | /// null |
411 | /// ] |
412 | /// }, |
413 | /// "friends" : [ |
414 | /// {"name" : "친구3" , "age" : 30}, |
415 | /// {"name" : "친구4" } |
416 | /// ]})); |
417 | /// ``` |
418 | pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> { |
419 | let mut selector: SelectorMut = SelectorMut::default(); |
420 | let value: &mut SelectorMut = selector.str_path(path)?.value(value).delete()?; |
421 | Ok(value.take().unwrap_or(default:Value::Null)) |
422 | } |
423 | |
424 | /// 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. |
425 | /// |
426 | /// ```rust |
427 | /// extern crate jsonpath_lib as jsonpath; |
428 | /// #[macro_use] extern crate serde_json; |
429 | /// |
430 | /// use serde_json::Value; |
431 | /// |
432 | /// let json_obj = json!({ |
433 | /// "school" : { |
434 | /// "friends" : [ |
435 | /// {"name" : "친구1" , "age" : 20}, |
436 | /// {"name" : "친구2" , "age" : 20} |
437 | /// ] |
438 | /// }, |
439 | /// "friends" : [ |
440 | /// {"name" : "친구3" , "age" : 30}, |
441 | /// {"name" : "친구4" } |
442 | /// ]}); |
443 | /// |
444 | /// let ret = jsonpath::replace_with(json_obj, "$..[?(@.age == 20)].age" , &mut |v| { |
445 | /// let age = if let Value::Number(n) = v { |
446 | /// n.as_u64().unwrap() * 2 |
447 | /// } else { |
448 | /// 0 |
449 | /// }; |
450 | /// |
451 | /// Some(json!(age)) |
452 | /// }).unwrap(); |
453 | /// |
454 | /// assert_eq!(ret, json!({ |
455 | /// "school" : { |
456 | /// "friends" : [ |
457 | /// {"name" : "친구1" , "age" : 40}, |
458 | /// {"name" : "친구2" , "age" : 40} |
459 | /// ] |
460 | /// }, |
461 | /// "friends" : [ |
462 | /// {"name" : "친구3" , "age" : 30}, |
463 | /// {"name" : "친구4" } |
464 | /// ]})); |
465 | /// ``` |
466 | pub fn replace_with<F>(value: Value, path: &str, fun: &mut F) -> Result<Value, JsonPathError> |
467 | where |
468 | F: FnMut(Value) -> Option<Value>, |
469 | { |
470 | let mut selector: SelectorMut = SelectorMut::default(); |
471 | let value: &mut SelectorMut = selector.str_path(path)?.value(value).replace_with(fun)?; |
472 | Ok(value.take().unwrap_or(default:Value::Null)) |
473 | } |
474 | |
475 | /// A pre-compiled expression. |
476 | /// |
477 | /// Calling the select function of this struct will re-use the existing, compiled expression. |
478 | /// |
479 | /// ## Example |
480 | /// |
481 | /// ```rust |
482 | /// extern crate jsonpath_lib as jsonpath; |
483 | /// #[macro_use] extern crate serde_json; |
484 | /// |
485 | /// let mut first_friend = jsonpath::Compiled::compile("$..friends[0]" ).unwrap(); |
486 | /// |
487 | /// let json_obj = json!({ |
488 | /// "school" : { |
489 | /// "friends" : [ |
490 | /// {"name" : "친구1" , "age" : 20}, |
491 | /// {"name" : "친구2" , "age" : 20} |
492 | /// ] |
493 | /// }, |
494 | /// "friends" : [ |
495 | /// {"name" : "친구3" , "age" : 30}, |
496 | /// {"name" : "친구4" } |
497 | /// ]}); |
498 | /// |
499 | /// // call a first time |
500 | /// |
501 | /// let json = first_friend.select(&json_obj).unwrap(); |
502 | /// |
503 | /// assert_eq!(json, vec![ |
504 | /// &json!({"name" : "친구3" , "age" : 30}), |
505 | /// &json!({"name" : "친구1" , "age" : 20}) |
506 | /// ]); |
507 | /// |
508 | /// // call a second time |
509 | /// |
510 | /// let json = first_friend.select(&json_obj).unwrap(); |
511 | /// |
512 | /// assert_eq!(json, vec![ |
513 | /// &json!({"name" : "친구3" , "age" : 30}), |
514 | /// &json!({"name" : "친구1" , "age" : 20}) |
515 | /// ]); |
516 | /// ``` |
517 | #[derive (Clone, Debug)] |
518 | pub struct Compiled { |
519 | node: Node, |
520 | } |
521 | |
522 | impl Compiled { |
523 | /// Compile a path expression and return a compiled instance. |
524 | /// |
525 | /// If parsing the path fails, it will return an error. |
526 | pub fn compile(path: &str) -> Result<Compiled, String> { |
527 | let node: Node = parser::Parser::compile(input:path)?; |
528 | Ok(Compiled{ |
529 | node |
530 | }) |
531 | } |
532 | |
533 | /// Execute the select operation on the pre-compiled path. |
534 | pub fn select<'a>(&self, value: &'a Value) -> Result<Vec<&'a Value>, JsonPathError> { |
535 | let mut selector: Selector<'_, '_> = Selector::default(); |
536 | selector.compiled_path(&self.node).value(value).select() |
537 | } |
538 | } |
539 | |