use regex::Regex;
use serde_json::{self, Value};
fn get_nested_value<'a>(json: &'a Value, key: &str) -> Option<&'a Value> {
let mut value = json;
for k in key.split('.') {
value = value.get(k)?;
}
Some(value)
}
pub fn json_to_markdown(json_data: &str, markdown: &str) -> serde_json::Result<String> {
let json: Value = serde_json::from_str(json_data)?;
let re = Regex::new(r"\{([a-zA-Z0-9_.]+)\}").unwrap();
let re_array = Regex::new(r"\...\{([a-zA-Z0-9_.]+)\}").unwrap();
let string_one = re_array.replace_all(markdown, |caps: ®ex::Captures| {
let key = caps.get(1).unwrap().as_str();
match get_nested_value(&json, key) {
Some(value) => {
let mut rendered = String::new();
if value.is_array() {
for (_, v) in value.as_array().unwrap().iter().enumerate() {
rendered.push_str(&format!("- {}\n", v).replace("\"", ""));
}
}
if value.is_object() {
for (k, v) in value.as_object().unwrap().iter() {
rendered.push_str(&format!("- {}: {}\n", k, v).replace("\"", ""));
}
}
rendered
}
None => caps.get(0).unwrap().as_str().to_string(),
}
});
let rendered = re.replace_all(&string_one, |caps: ®ex::Captures| {
let key = caps.get(1).unwrap().as_str();
match get_nested_value(&json, key) {
Some(value) => value.to_string().replace("\"", ""),
None => caps.get(0).unwrap().as_str().to_string(),
}
});
Ok(rendered.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_json_to_markdown() {
let json_data = r#"
{
"name": "John Doe",
"age": 43,
"contact": ["+44 1234567", "+44 2345678"]
}"#;
let markdown = r#"
# {name}
## {age}
### Contact Details
...{contact}
"#;
let rendered = json_to_markdown(json_data, markdown).unwrap();
assert!(rendered.contains("John Doe"));
assert!(rendered.contains("43"));
assert!(rendered.contains("+44 1234567"));
assert!(rendered.contains("+44 2345678"));
}
}