How about simplifying VNode struct using alias variant?
I tried re-writing the code like below.
use serde::{Deserialize, Serialize};
use std::fs;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct VNode {
#[serde(rename = "type")]
pub type_field: String,
#[serde(alias = "tag",alias = "value")]
pub tag_name: String,
pub attributes: Vec<(String,String)>,
pub children: Vec<VNode>,
}
impl VNode {
fn render(&self) -> String {
let attrs = &self.attributes.iter()
.map(|(key, value)| format!("{}=\"{}\"", key, value))
.collect::<Vec<_>>()
.join(" ");
let children = &self.children.iter()
.map(|child| child.render())
.collect::<Vec<_>>()
.join(" ");
format!("<{} {}>{}</{}>", &self.tag_name, attrs, children, &self.tag_name)
}
}
fn parse_json_to_vdom(json: &str) -> Result<VNode, serde_json::Error> {
serde_json::from_str::<VNode>(json)
}
fn read_json_from_file(file_path: &str) -> Result<String, std::io::Error> {
fs::read_to_string(file_path)
}
fn main() {
let file_path = "path/to/your/file.json"; // Update this path to your JSON file's location
// Read JSON from the file
let json_result = read_json_from_file(file_path);
match json_result {
Ok(json) => {
// Parse the JSON into the virtual DOM
match parse_json_to_vdom(&json) {
Ok(vdom) => {
// Render the virtual DOM to HTML
let html_output = vdom.render();
println!("Rendered HTML:\n{}", html_output);
}
Err(e) => println!("Failed to parse JSON: {}", e),
}
}
Err(e) => println!("Failed to read file: {}", e),
}
}
Output:
Rendered HTML:
<div class="container"><h1 ><Hello, Rust! ></Hello, Rust!></h1> <p ><This is a virtual DOM parsed from JSON. ></This is a virtual DOM parsed from JSON.></p></div>