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

171 lines
6.3 KiB
Rust

// use serde::{de::value, Serialize};
use serde_json::{json, Value};
use integr_structs::api::v3::{Metric, MetricOutput};
/// A JSON-parser struct
///
/// Using in metric extracting from Server Response
/// with metrics mechanism
///
/// # Example
///
/// ```
/// use api-grub::json::JsonParser;
/// use use integr_structs::api::v3::Metric;
///
/// let json = b""flat1" : { "room1" : { "rt_tempo" : "+16" }}".to_vec();
///
/// assert!(!JsonParser::parse(vec![Metric::template()], json).is_empty());
/// ```
pub struct JsonParser;
impl JsonParser {
pub fn parse(targets: &Vec<Metric>, json: &str) -> Vec<MetricOutput> {
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));
}
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<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": tag_name, "tag_value": val})
),
serde_json::from_value::<serde_json::Map<String, Value>>(metrics[idx].clone()))
})
.for_each(|(tags, val)| {
if val.is_ok() && tags.is_ok() {
let mut tags = tags.unwrap();
let mut val = val.unwrap();
tags.append(&mut val);
dbg!(&tags);
values.push(json!(tags));
}
});
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
}
}