JSON format import/export for graph data exchange.
This module provides comprehensive JSON serialization capabilities for graph data, supporting multiple formats used by popular visualization libraries, as well as import functionality for round-trip serialization.
Format Support
- Generic: Full metadata with type preservation
- D3Force: D3.js force-directed graphs
- Cytoscape: Cytoscape.js network visualization
- VisJs: vis.js network format
- NetworkX: Python NetworkX compatibility
Examples
Export to JSON
iex> graph = Yog.directed()
...> |> Yog.add_node(1, "Alice")
...> |> Yog.add_node(2, "Bob")
...> |> Yog.add_edge_ensure(from: 1, to: 2, with: "follows")
iex>
iex> json_string = Yog.IO.JSON.to_json(graph)
iex> String.contains?(json_string, "Alice")
trueImport from JSON
iex> json = ~s|{"graph_type":"directed","nodes":[{"id":1,"data":"Alice"},{"id":2,"data":"Bob"}],"edges":[{"source":1,"target":2,"weight":"follows"}]}|
iex> {:ok, graph} = Yog.IO.JSON.from_json(json)
iex> Yog.Model.order(graph)
2Import from Map (PostgreSQL JSONB)
iex> map = %{
...> "graph_type" => "undirected",
...> "nodes" => [%{"id" => 1, "data" => "A"}, %{"id" => 2, "data" => "B"}],
...> "edges" => [%{"source" => 1, "target" => 2, "weight" => 1}]
...> }
iex> {:ok, graph} = Yog.IO.JSON.from_map(map)
iex> Yog.Model.edge_count(graph)
1
Summary
Functions
Creates default export options for String node and edge data.
Converts a JsonError to a string.
Creates export options with custom serializers for generic types.
Parses a JSON string and creates a graph.
Parses a JSON string and creates a graph, raising on error.
Creates a graph from a map (useful for PostgreSQL JSONB).
Detects the JSON graph format of the given input.
Detects the JSON graph format, raising on error for string input.
Quick export for Cytoscape.js with default settings.
Quick export for D3.js force-directed graphs with default settings.
Converts a graph to a JSON string according to options.
Exports a graph to a JSON file.
Exports a multigraph to a JSON file.
Converts a multigraph to a JSON string.
Quick export for vis.js networks with default settings.
Writes a graph to a JSON file using default export options.
Writes a graph to a JSON file with custom export options.
Functions
@spec default_export_options() :: tuple()
Creates default export options for String node and edge data.
Time complexity: $\mathcal{O}(1)$
Converts a JsonError to a string.
Time complexity: $\mathcal{O}(1)$
Creates export options with custom serializers for generic types.
Raises ArgumentError if serializers or keyword options are invalid.
Time complexity: $\mathcal{O}(1)$
Parses a JSON string and creates a graph.
Supports the generic Yog format and common variations.
Raises ArgumentError if json_string is not a binary string.
Time complexity: $\mathcal{O}(V + E)$
Parameters
json_string- JSON string to parse
Returns
{:ok, graph}- Successfully parsed graph{:error, reason}- Parsing failed
Examples
iex> json = ~s|{"graph_type":"directed","nodes":[{"id":1,"data":"A"}],"edges":[]}|
iex> {:ok, graph} = Yog.IO.JSON.from_json(json)
iex> Yog.Model.order(graph)
1
iex> # NetworkX format
iex> nx_json = ~s|{"directed":true,"multigraph":false,"nodes":[{"id":1}],"links":[]}|
iex> {:ok, graph} = Yog.IO.JSON.from_json(nx_json)
iex> Yog.Model.type(graph)
:directed
iex> # D3 format (nodes + links)
iex> d3_json = ~s|{"nodes":[{"id":1},{"id":2}],"links":[{"source":1,"target":2,"weight":5}]}|
iex> {:ok, graph} = Yog.IO.JSON.from_json(d3_json)
iex> Yog.Model.edge_count(graph)
1
iex> # Cytoscape format
iex> cy_json = ~s|{"elements":[{"data":{"id":1}},{"data":{"id":2}},{"data":{"source":1,"target":2}}]}|
iex> {:ok, graph} = Yog.IO.JSON.from_json(cy_json)
iex> Yog.Model.order(graph)
2
Parses a JSON string and creates a graph, raising on error.
Time complexity: $\mathcal{O}(V + E)$
Examples
iex> json = ~s|{"graph_type":"undirected","nodes":[],"edges":[]}|
iex> graph = Yog.IO.JSON.from_json!(json)
iex> Yog.Model.order(graph)
0
Creates a graph from a map (useful for PostgreSQL JSONB).
Auto-detects format based on keys present in the map.
Raises ArgumentError if map is not a map.
Time complexity: $\mathcal{O}(V + E)$
Parameters
map- Map containing graph data
Supported Formats
- Yog Generic:
%{"graph_type" => "directed", "nodes" => [...], "edges" => [...]} - NetworkX:
%{"directed" => true, "nodes" => [...], "links" => [...]} - D3:
%{"nodes" => [...], "links" => [...]} - Cytoscape:
%{"elements" => [...]} - VisJs:
%{"nodes" => [...], "edges" => [...]}(withfrom/to)
Examples
iex> map = %{
...> "graph_type" => "undirected",
...> "nodes" => [%{"id" => 1, "data" => "Node A"}],
...> "edges" => []
...> }
iex> {:ok, graph} = Yog.IO.JSON.from_map(map)
iex> Yog.Model.order(graph)
1
iex> # From PostgreSQL JSONB (simple format)
iex> simple = %{
...> "type" => "directed",
...> "nodes" => [%{"id" => 1}, %{"id" => 2}],
...> "edges" => [%{"from" => 1, "to" => 2}]
...> }
iex> {:ok, graph} = Yog.IO.JSON.from_map(simple)
iex> Yog.has_edge?(graph, 1, 2)
true
@spec json_type(String.t() | map()) :: {:ok, atom()} | {:error, Jason.DecodeError.t()}
Detects the JSON graph format of the given input.
Supports detection from both JSON strings and decoded maps.
Raises ArgumentError if input is neither a binary string nor a map.
Time complexity: $\mathcal{O}(V + E)$
Parameters
input- JSON string or map to detect the format of
Returns
{:ok, type}- One of:yog_generic,:network_x,:d3_force,:cytoscape,:visjs, or:simple{:error, reason}- If input is a string and parsing fails
Examples
iex> json = ~s|{"graph_type":"directed","nodes":[],"edges":[]}|
iex> Yog.IO.JSON.json_type(json)
{:ok, :yog_generic}
iex> network_x_map = %{"nodes" => [], "links" => [], "directed" => true}
iex> Yog.IO.JSON.json_type(network_x_map)
{:ok, :network_x}
iex> d3_force_map = %{"nodes" => [], "links" => []}
iex> Yog.IO.JSON.json_type(d3_force_map)
{:ok, :d3_force}
Detects the JSON graph format, raising on error for string input.
Time complexity: $\mathcal{O}(V + E)$
Examples
iex> json = ~s|{"elements": []}|
iex> Yog.IO.JSON.json_type!(json)
:cytoscape
@spec to_cytoscape_json(Yog.graph() | Yog.DAG.t(), (any() -> any()), (any() -> any())) :: String.t()
Quick export for Cytoscape.js with default settings.
Raises ArgumentError if serializers or graph are invalid.
Time complexity: $\mathcal{O}(V + E)$
Quick export for D3.js force-directed graphs with default settings.
Raises ArgumentError if serializers or graph are invalid.
Time complexity: $\mathcal{O}(V + E)$
Converts a graph to a JSON string according to options.
Raises ArgumentError if graph or options are invalid.
Time complexity: $\mathcal{O}(V + E)$
Exports a graph to a JSON file.
Raises ArgumentError if path is not a binary string or graph/options are invalid.
Time complexity: $\mathcal{O}(V + E)$ + file I/O
Exports a multigraph to a JSON file.
Raises ArgumentError if path is not a binary string.
Time complexity: $\mathcal{O}(V + E)$ + file I/O
Converts a multigraph to a JSON string.
Time complexity: $\mathcal{O}(V + E)$
Quick export for vis.js networks with default settings.
Raises ArgumentError if serializers or graph are invalid.
Time complexity: $\mathcal{O}(V + E)$
Writes a graph to a JSON file using default export options.
Raises ArgumentError if path is not a binary string or graph is invalid.
Time complexity: $\mathcal{O}(V + E)$ + file I/O
Writes a graph to a JSON file with custom export options.
Raises ArgumentError if path is not a binary string or graph/options are invalid.
Time complexity: $\mathcal{O}(V + E)$ + file I/O