use crate::{CodeGraph, Node, Result};
use serde_json::{json, Value};
use std::collections::HashSet;
pub fn export_json(graph: &CodeGraph) -> Result<String> {
let mut nodes_array = Vec::new();
let mut links_array = Vec::new();
for node_id in 0..graph.node_count() as u64 {
if let Ok(node) = graph.get_node(node_id) {
nodes_array.push(node_to_json(node_id, node));
}
}
for edge_id in 0..graph.edge_count() as u64 {
if let Ok(edge) = graph.get_edge(edge_id) {
links_array.push(json!({
"id": edge_id,
"source": edge.source_id,
"target": edge.target_id,
"type": format!("{:?}", edge.edge_type),
"properties": properties_to_json(&edge.properties),
}));
}
}
let result = json!({
"nodes": nodes_array,
"links": links_array,
});
Ok(serde_json::to_string_pretty(&result).expect("Failed to serialize JSON"))
}
pub fn export_json_filtered(
graph: &CodeGraph,
node_filter: impl Fn(&Node) -> bool,
include_edges: bool,
) -> Result<String> {
let mut nodes_array = Vec::new();
let mut filtered_ids = HashSet::new();
for node_id in 0..graph.node_count() as u64 {
if let Ok(node) = graph.get_node(node_id) {
if node_filter(node) {
nodes_array.push(node_to_json(node_id, node));
filtered_ids.insert(node_id);
}
}
}
let mut links_array = Vec::new();
if include_edges {
for edge_id in 0..graph.edge_count() as u64 {
if let Ok(edge) = graph.get_edge(edge_id) {
if filtered_ids.contains(&edge.source_id) && filtered_ids.contains(&edge.target_id)
{
links_array.push(json!({
"id": edge_id,
"source": edge.source_id,
"target": edge.target_id,
"type": format!("{:?}", edge.edge_type),
"properties": properties_to_json(&edge.properties),
}));
}
}
}
}
let result = json!({
"nodes": nodes_array,
"links": links_array,
});
Ok(serde_json::to_string_pretty(&result).expect("Failed to serialize JSON"))
}
fn node_to_json(node_id: u64, node: &Node) -> Value {
json!({
"id": node_id,
"type": format!("{:?}", node.node_type),
"properties": properties_to_json(&node.properties),
})
}
fn properties_to_json(props: &crate::PropertyMap) -> Value {
let mut obj = serde_json::Map::new();
for (key, value) in props.iter() {
let json_value = match value {
crate::PropertyValue::String(s) => json!(s),
crate::PropertyValue::Int(i) => json!(i),
crate::PropertyValue::Float(f) => json!(f),
crate::PropertyValue::Bool(b) => json!(b),
crate::PropertyValue::StringList(v) => json!(v),
crate::PropertyValue::IntList(v) => json!(v),
crate::PropertyValue::Null => json!(null),
};
obj.insert(key.clone(), json_value);
}
Value::Object(obj)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::PropertyMap;
#[test]
fn test_properties_to_json() {
let mut props = PropertyMap::new();
props.insert("name", "test");
props.insert("count", 42);
let json = properties_to_json(&props);
assert!(json.is_object());
assert_eq!(json["name"], "test");
assert_eq!(json["count"], 42);
}
}