1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
use std::fmt::Debug; use crate::errors::{FhttpError, Result}; #[derive(Debug, Eq, PartialEq, Clone)] pub enum ResponseHandler { Json { json_path: String }, } impl ResponseHandler { pub fn process_body( &self, body: &str ) -> Result<String> { match self { ResponseHandler::Json { json_path } => process_body_json(json_path, body) } } } fn process_body_json( json_path: &str, body: &str ) -> Result<String> { use jsonpath::Selector; use serde_json::Value; let value: Value = serde_json::from_str(body) .map_err(|e| FhttpError::new(format!( "Error parsing response body as json: {}. Body was '{}'", e.to_string(), body )))?; let mut selector = Selector::new(); let json_path_results = selector .str_path(json_path).unwrap() .value(&value) .select() .unwrap(); let result = match json_path_results.len() { 0 => Value::String("".into()), _ => json_path_results[0].clone(), }; match result { Value::String(string) => Ok(string), _ => Ok(serde_json::to_string(&result).unwrap()) } } #[cfg(test)] mod json_tests { use indoc::indoc; use super::*; #[test] fn should_apply_the_jsonpath_expression() { let body = indoc!(" { \"a\": { \"b\": { \"c\": \"success\" }, \"c\": \"failure\" } } "); let handler = ResponseHandler::Json { json_path: "$.a.b.c".into() }; let result = handler.process_body(body); assert_eq!(result, Ok(String::from("success"))); } #[test] fn should_convert_numbers_to_string() { let body = indoc!(" { \"a\": { \"b\": { \"c\": 3.141 } } } "); let handler = ResponseHandler::Json { json_path: "$.a.b.c".into() }; let result = handler.process_body(body); assert_eq!(result, Ok(String::from("3.141"))); } }