use super::{Graph, GraphOptions};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonGraph<N, E, G> {
pub options: JsonGraphOptions,
pub nodes: Vec<JsonNode<N>>,
pub edges: Vec<JsonEdge<E>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<G>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonGraphOptions {
pub directed: bool,
pub multigraph: bool,
pub compound: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonNode<N> {
pub v: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<N>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonEdge<E> {
pub v: String,
pub w: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<E>,
}
pub fn graph_to_json<N: Clone + Serialize, E: Clone + Serialize, G: Clone + Serialize>(
g: &Graph<N, E>,
graph_label: Option<&G>,
) -> JsonGraph<N, E, G> {
let nodes = g
.nodes()
.iter()
.map(|v| {
let value = g.node(v).cloned();
let parent = if g.is_compound() {
g.parent(v).map(|p| p.to_string())
} else {
None
};
JsonNode {
v: v.clone(),
value,
parent,
}
})
.collect();
let edges = g
.edges()
.iter()
.map(|e| {
let value = g.edge(&e.v, &e.w, e.name.as_deref()).cloned();
JsonEdge {
v: e.v.clone(),
w: e.w.clone(),
name: e.name.clone(),
value,
}
})
.collect();
JsonGraph {
options: JsonGraphOptions {
directed: g.is_directed(),
multigraph: g.is_multigraph(),
compound: g.is_compound(),
},
nodes,
edges,
value: graph_label.cloned(),
}
}
pub fn graph_from_json<N: Clone, E: Clone, G>(
json: JsonGraph<N, E, G>,
) -> (Graph<N, E>, Option<G>) {
let mut g = Graph::with_options(GraphOptions {
directed: json.options.directed,
multigraph: json.options.multigraph,
compound: json.options.compound,
});
for node in &json.nodes {
g.set_node(node.v.clone(), node.value.clone());
}
if json.options.compound {
for node in &json.nodes {
if let Some(parent) = &node.parent {
g.set_parent(&node.v, Some(parent.as_str()));
}
}
}
for edge in json.edges {
g.set_edge(edge.v, edge.w, edge.value, edge.name.as_deref());
}
(g, json.value)
}