// use serde::{de::value, Serialize}; use serde_json::{json, Value}; use integr_structs::api::v3::{Metric, MetricOutput}; pub struct JsonParser; impl JsonParser { pub fn parse(targets: &Vec, json: &str) -> Vec { 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(MetricOutput::new_with_slices(&target.id, &target.json_type, &target.addr, metric)); } res_vec } fn get_sum_of_metrics_in_array(target: &Metric, 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: &Metric, 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 } }