integration-module/crates/api-grub/src/json.rs

154 lines
5.9 KiB
Rust

// 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<Metric>, json: &str) -> Value {
let mut res_vec: Vec<MetricOutput> = 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));
}
serde_json::to_value(res_vec).unwrap_or(Value::Null)
}
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<Value> = 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::<Vec<&str>>();
// 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::<String>();
// dbg!(&key_tag);
key.chars()
.enumerate()
.filter(|(idx, _)| *idx < key_idx)
.map(|(_, chr)| chr)
.collect::<String>()
// 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::<Vec<String>>();
// 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<Value>, metrics: &Vec<Value>, tag_name: &str) -> Vec<Value> {
if tag_name.is_empty() {
return metrics.clone();
}
// array[0].as_object().unwrap_or(json!(Value::Null))
let mut values: Vec<Value> = Vec::new();
array.iter()
.enumerate()
.map(|(idx, val)| {
let val = val.get(tag_name).unwrap_or(&Value::Null).clone();
(serde_json::from_value::<serde_json::Map<String, Value>>(json!({tag_name: val})),
serde_json::from_value::<serde_json::Map<String, 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<Value>, fields: &Vec<String>) -> Vec<Value> {
let mut values: Vec<Value> = 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::<Vec<&str>>();
for key in target_attr_vec {
match value_json.get(key) {
Some(val) => value_json = val.clone(),
None => return Value::Null,
}
}
value_json
}
}