Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Last active September 25, 2024 18:17
Show Gist options
  • Save matthewjberger/da34863285fab9f6d93b944e31c0c98d to your computer and use it in GitHub Desktop.
Save matthewjberger/da34863285fab9f6d93b944e31c0c98d to your computer and use it in GitHub Desktop.
use serde_json::Value;
use std::collections::HashMap;
pub fn expand_json_template(template: &str, tokens: &HashMap<String, String>) -> Option<String> {
let substituted = substitute_tokens(template, tokens);
match serde_json::from_str::<Value>(&substituted) {
Ok(value) => serde_json::to_string_pretty(&value).ok(),
Err(e) => {
println!("Error parsing JSON after substitution: {}", e);
None
}
}
}
fn substitute_tokens(template: &str, tokens: &HashMap<String, String>) -> String {
let mut result = template.to_string();
for (key, value) in tokens {
let token = format!("{{{{{}}}}}", key);
result = result.replace(&token, value);
}
result
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_simple_substitution() {
let mut tokens = HashMap::new();
tokens.insert("name".to_string(), r#""John Doe""#.to_string());
tokens.insert("age".to_string(), "30".to_string());
let input = r#"{"name": {{name}}, "age": {{age}}}"#;
let expected = json!({"name": "John Doe", "age": 30});
let result = expand_json_template(input, &tokens).unwrap();
assert_eq!(serde_json::from_str::<Value>(&result).unwrap(), expected);
}
#[test]
fn test_nested_object_substitution() {
let mut tokens = HashMap::new();
tokens.insert("user_info".to_string(), r#"{"email": "john@example.com", "active": true}"#.to_string());
let input = r#"{"user": {{user_info}}}"#;
let expected = json!({"user": {"email": "john@example.com", "active": true}});
let result = expand_json_template(input, &tokens).unwrap();
assert_eq!(serde_json::from_str::<Value>(&result).unwrap(), expected);
}
#[test]
fn test_array_substitution() {
let mut tokens = HashMap::new();
tokens.insert("numbers".to_string(), "[1, 2, 3]".to_string());
let input = r#"{"data": {{numbers}}}"#;
let expected = json!({"data": [1, 2, 3]});
let result = expand_json_template(input, &tokens).unwrap();
assert_eq!(serde_json::from_str::<Value>(&result).unwrap(), expected);
}
#[test]
fn test_partial_string_substitution() {
let mut tokens = HashMap::new();
tokens.insert("domain".to_string(), "example.com".to_string());
let input = r#"{"email": "john@{{domain}}"}"#;
let expected = json!({"email": "john@example.com"});
let result = expand_json_template(input, &tokens).unwrap();
assert_eq!(serde_json::from_str::<Value>(&result).unwrap(), expected);
}
#[test]
fn test_multiple_substitutions() {
let mut tokens = HashMap::new();
tokens.insert("name".to_string(), r#""Alice""#.to_string());
tokens.insert("age".to_string(), "25".to_string());
tokens.insert("city".to_string(), r#""New York""#.to_string());
let input = r#"{"name": {{name}}, "age": {{age}}, "address": {"city": {{city}}}}"#;
let expected = json!({
"name": "Alice",
"age": 25,
"address": {"city": "New York"}
});
let result = expand_json_template(input, &tokens).unwrap();
assert_eq!(serde_json::from_str::<Value>(&result).unwrap(), expected);
}
#[test]
fn test_no_substitution_needed() {
let tokens = HashMap::new();
let input = r#"{"name": "John", "age": 30}"#;
let expected = json!({"name": "John", "age": 30});
let result = expand_json_template(input, &tokens).unwrap();
assert_eq!(serde_json::from_str::<Value>(&result).unwrap(), expected);
}
#[test]
fn test_missing_token() {
let tokens = HashMap::new();
let input = r#"{"name": {{name}}}"#;
assert!(expand_json_template(input, &tokens).is_none());
}
#[test]
fn test_invalid_json_template() {
let tokens = HashMap::new();
let input = r#"{"name": {{name}}, "age": }"#; // Invalid JSON
assert!(expand_json_template(input, &tokens).is_none());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment