Skip to content
Snippets Groups Projects
Verified Commit 33612ba5 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

[NSS] Refactor more jq program loading code into function

parent 44bde3bb
No related branches found
No related tags found
No related merge requests found
...@@ -151,73 +151,67 @@ fn get_data(conf: &Config, prefix: &str, endpoint: &str, param: String, token: & ...@@ -151,73 +151,67 @@ fn get_data(conf: &Config, prefix: &str, endpoint: &str, param: String, token: &
.text()?) .text()?)
} }
fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str, rev: bool) -> Option<String> { fn get_jq_prog(conf: &Config, prefix: &str, endpoint: &str, multi: bool, rev: bool) -> jq_rs::Result<jq_rs::JqProgram> {
// Generate config key to find jq program under
let prog_key = match rev { let prog_key = match rev {
false => full_key(vec![prefix, "maps", endpoint]), false => full_key(vec![prefix, "maps", endpoint]),
true => full_key(vec![prefix, "maps.rev", endpoint]), true => full_key(vec![prefix, "maps.rev", endpoint]),
}; };
match get_optional(&conf, &prog_key) {
Some(v) => Some (v), // Retrieve jq program code from config
let mut jq_code: String = match get_optional(&conf, &prog_key) {
// We got the value immediately
Some(v) => v,
None => { None => {
if rev { if rev {
// Do not fallback to more generic program for reverse mapping // Do not fallback to more generic program for reverse mapping
return None; ".".to_string()
} } else {
// Try falling back to more generic program // Try falling back to more generic program
match endpoint.find('.') { match endpoint.find('.') {
Some(i) => { Some(i) => {
debug!("JQ mapping program for {} not found; trying more generic definition", endpoint); debug!("JQ mapping program for {} not found; trying more generic definition", endpoint);
get_jq_prog(conf, prefix, &endpoint[..i], rev) // Call recursively (and return verbatim, as we get a compiled program)
}, return get_jq_prog(conf, prefix, &endpoint[..i], multi, rev)
None => None }
// Lookup failed ultimately; fallback to jq "identity" (no-op)
None => ".".to_string()
}
} }
} }
};
// If multi mode is passed, the program will be applied to an array of entries
// We thus wrap it in a call to jq's `map()`
if multi {
jq_code = "map(".to_string() + &jq_code + ")";
} }
debug!("Compiling JQ program for endpoint {}: {}", endpoint, jq_code);
jq_rs::compile(&jq_code)
} }
pub fn get_data_jq<T: for<'de> Deserialize<'de>, V: Serialize>(conf: &Config, prefix: &str, endpoint: &str, param: V, token: &BasicTokenResponse, multi: bool) -> Result<T, Box<dyn error::Error>> { pub fn get_data_jq<T: for<'de> Deserialize<'de>, V: Serialize>(conf: &Config, prefix: &str, endpoint: &str, param: V, token: &BasicTokenResponse, multi: bool) -> Result<T, Box<dyn error::Error>> {
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint, false); // Get jq mapping programs for forward and reverse mappings
let jq_code = match res { let mut jq_prog_fwd = get_jq_prog(&conf, prefix, endpoint, multi, false)?;
Some(s) => { let mut jq_prog_rev = get_jq_prog(&conf, prefix, endpoint, false, true)?;
debug!("Found jq mapping program for endpoint {}: {}", endpoint, s);
match multi {
true => "map(".to_string() + &s + ")",
false => s
}
},
None => {
debug!("No jq mapping program for endpoint {}; using default (no-op)", endpoint);
".".to_string()
}
};
let mut jq_prog = jq_rs::compile(&jq_code)?;
let res: Option<String> = get_jq_prog(&conf, prefix, endpoint, true);
let jq_code = match res {
Some(s) => {
debug!("Found jq reverse mapping program for endpoint {}: {}", endpoint, s);
s
},
None => {
debug!("No jq reverse mapping program for endpoint {}; using default (no-op)", endpoint);
".".to_string()
}
};
let mut jq_prog_rev = jq_rs::compile(&jq_code)?;
// Convert and transform the passed param using the reverse JQ mapping program // Convert and transform the passed param using the reverse JQ mapping program
// 1. Serialize into JSON value (atomic) to be bale to pass into jq // 1. Serialize into JSON value (atomic) to be bale to pass into jq
let param_serialized = serde_json::to_string(&param)?; let param = serde_json::to_string(&param)?;
// 2. Transform using the JQ program loaded above // 2. Transform using the JQ program loaded above
let param_trans = jq_prog_rev.run(&param_serialized)?.trim().to_string(); let param = jq_prog_rev.run(&param)?.trim().to_string();
// 3. Deserialize into serde_json value so we get numbers as numbers, strings properly unquoted // 3. Deserialize into serde_json value so we get numbers as numbers, strings properly unquoted
let param_deserialized: serde_json::Value = serde_json::from_str(&param_trans)?; let param: serde_json::Value = serde_json::from_str(&param)?;
let param = match param_deserialized { let param = match param {
serde_json::Value::String(v) => v, // We want strings verbatim without JSON quoting serde_json::Value::String(v) => v, // We want strings verbatim without JSON quoting
_ => param_deserialized.to_string() // We want numbers converted to string _ => param.to_string() // We want numbers converted to string
}; };
let data_raw = get_data(&conf, prefix, endpoint, param, token)?; // Retrieve data via HTTP and transform using jq forward mapping program
let data_trans = jq_prog.run(&data_raw)?; let data = get_data(&conf, prefix, endpoint, param, token)?;
let data = jq_prog_fwd.run(&data)?;
Ok(serde_json::from_str(&data_trans)?) // Deserialize transformed JSON and return
Ok(serde_json::from_str(&data)?)
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment