diff --git a/crates/api-grub/src/json.rs b/crates/api-grub/src/json.rs new file mode 100644 index 0000000..f0f64d6 --- /dev/null +++ b/crates/api-grub/src/json.rs @@ -0,0 +1,176 @@ +// use serde::{de::value, Serialize}; +use serde_json::{json, Value}; +use integr_structs::api::v3::{TestMetric, TestMetricOutput}; + +pub struct JsonParser; + +impl JsonParser { + pub fn parse(targets: &Vec, json: &str) -> Value { + let mut res_vec: Vec = Vec::new(); + for target in targets { + let metric = match target.addr.contains("[") { + true => JsonParser::get_sum_of_metrics_in_array(target, json), + false => JsonParser::get_metric(target, json), + }; + res_vec.push(TestMetricOutput::new_with_slices(&target.id, &target.json_type, metric)); + } + serde_json::to_value(res_vec).unwrap_or(Value::Null) + } + fn get_sum_of_metrics_in_array(target: &TestMetric, json: &str) -> Value { + if target.addr.is_empty() { + return Value::Null; + } + + let mut vec_value: Vec = Vec::new(); + let mut array_key = String::new(); + let mut value_json: Value = serde_json::from_str(json).unwrap_or(Value::Null); + + let target_attr_vec = target.addr + .split_terminator('.') + .collect::>(); + // for keys in [] brackets + let mut key_tag = String::new(); + + for (global_idx, &key) in target_attr_vec.iter().enumerate() { + // if array + let key_checked = if key.contains('[') { + let key_idx = key.find("[").unwrap(); + key_tag = key.chars() + .enumerate() + .filter(|(idx, chr)| *idx > key_idx && *chr != ']') + .map(|(_, chr)| chr) + .collect::(); + dbg!(&key_tag); + key.chars() + .enumerate() + .filter(|(idx, _)| *idx < key_idx) + .map(|(_, chr)| chr) + .collect::() + // dbg!(value_json.get(&array_key).unwrap_or(&Value::Null)); + // value_json = value_json.get(array_key).unwrap_or(&Value::Null).clone(); + // continue; + // new_key.as_str() + // dbg!(key); APPROVED + // TODO: need to check key in [] type of [KEY] + } else {key.to_owned()}; + + // if already array + match value_json.get(key_checked) { + Some(val) => { + match val { + Value::Array(array) => { + // form new target array + let new_array_target = target_attr_vec + .iter() + .enumerate() + .filter(|(idx, _)| *idx > global_idx) + .map(|(_, &chr)| chr.to_owned()) + .collect::>(); + // get_values_in_array + // get_tags_in_array + // // slice_tags_with_values + // dbg!(&array); + // dbg!(&new_array_target); + let res_arr = Self::get_values_in_array(array, &new_array_target); + if &key_tag == "" { + return res_arr.into(); + } + return Self::slice_with_tags_in_array(array, &res_arr, &key_tag).into() + + }, + _ => value_json = val.clone(), + } + }, + None => return Value::Null, + } + } + value_json + } + + fn slice_with_tags_in_array(array: &Vec, metrics: &Vec, tag_name: &str) -> Vec { + if tag_name.is_empty() { + return metrics.clone(); + } + // array[0].as_object().unwrap_or(json!(Value::Null)) + let mut values: Vec = Vec::new(); + array.iter() + .enumerate() + .map(|(idx, val)| { + let val = val.get(tag_name).unwrap_or(&Value::Null).clone(); + (serde_json::from_value::>(json!({tag_name: val})), + serde_json::from_value::>(metrics[idx].clone())) + }) + .for_each(|(key, val)| { + // dbg!(&key); + if key.is_ok() && val.is_ok() { + let mut key = key.unwrap(); + let mut val = val.unwrap(); + key.append(&mut val); + values.push(json!(key)); + } + }); + if values.len() == 0 { + return metrics.clone(); + } + values + } + fn get_values_in_array(array: &Vec, fields: &Vec) -> Vec { + let mut values: Vec = Vec::new(); + for obj in array { + // dbg!(obj); + let mut obrez = obj.clone(); + for field in fields { + obrez = obrez.get(field).unwrap_or(&Value::Null).clone(); + match obrez { + Value::Object(_) => {continue}, + _ => { + values.push(json!({field: obrez.clone()})); + }, + // None => {values.push(Value::Null)}, + } + } + } + values + } + + fn get_metric(target: &TestMetric, json: &str) -> Value { + if target.addr.is_empty() { + return Value::Null; + } + let mut value_json: Value = serde_json::from_str(json).unwrap_or(Value::Null); + + let target_attr_vec = target.addr + .split_terminator('.') + .collect::>(); + for key in target_attr_vec { + match value_json.get(key) { + Some(val) => value_json = val.clone(), + None => return Value::Null, + } + } + value_json + } +} + + +// pub struct TestMetric { +// pub id : String, +// pub json_type : String, +// pub addr : String, +// } + +// #[derive(Serialize)] +// struct TestMetricOutput { +// id : String, +// json_type : String, +// value : Value, +// } +// impl TestMetricOutput { +// fn new_with_slices(id : &str, json_type : &str, value : Value) -> Self { +// TestMetricOutput { +// id : id.to_string(), +// json_type : json_type.to_string(), +// value : value, +// } +// } +// } \ No newline at end of file diff --git a/crates/api-grub/src/main.rs b/crates/api-grub/src/main.rs index 2fe4a95..5997ae8 100644 --- a/crates/api-grub/src/main.rs +++ b/crates/api-grub/src/main.rs @@ -1,6 +1,7 @@ mod config; mod net; mod logger; +mod json; use anyhow::Result; use integr_structs::api::ApiConfigV2; diff --git a/crates/integr-structs/src/api.rs b/crates/integr-structs/src/api.rs index c062da7..7712b28 100644 --- a/crates/integr-structs/src/api.rs +++ b/crates/integr-structs/src/api.rs @@ -144,4 +144,29 @@ impl ProcessedEndpoint { let val = ProcessedEndpoint::new(&keys.id, &keys.name, &keys.url, &keys.method,hm); Ok(to_string_pretty(&val)?) } +} + +pub mod v3 { + pub use super::*; + pub struct TestMetric { + pub id : String, + pub json_type : String, + pub addr : String, + } + + #[derive(Serialize)] + pub struct TestMetricOutput { + id : String, + json_type : String, + value : Value, + } + impl TestMetricOutput { + pub fn new_with_slices(id : &str, json_type : &str, value : Value) -> Self { + TestMetricOutput { + id : id.to_string(), + json_type : json_type.to_string(), + value : value, + } + } + } } \ No newline at end of file