# `Yog.IO.JSON`
[🔗](https://github.com/code-shoily/yog_ex/blob/v0.97.1/lib/yog/io/json.ex#L1)

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")
    true

### Import 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)
    2

### Import 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

# `default_export_options`

Creates default export options for String node and edge data.

# `error_to_string`

Converts a JsonError to a string.

# `export_options_with`

Creates export options with custom serializers for generic types.

# `from_json`

```elixir
@spec from_json(String.t()) :: {:ok, Yog.graph()} | {:error, String.t()}
```

Parses a JSON string and creates a graph.

Supports the generic Yog format and common variations.

## 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

# `from_json!`

```elixir
@spec from_json!(String.t()) :: Yog.graph()
```

Parses a JSON string and creates a graph, raising on error.

## Examples

    iex> json = ~s|{"graph_type":"undirected","nodes":[],"edges":[]}|
    iex> graph = Yog.IO.JSON.from_json!(json)
    iex> Yog.Model.order(graph)
    0

# `from_map`

```elixir
@spec from_map(map()) :: {:ok, Yog.graph()} | {:error, String.t()}
```

Creates a graph from a map (useful for PostgreSQL JSONB).

Auto-detects format based on keys present in the map.

## 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" => [...]}` (with `from`/`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

# `json_type`

```elixir
@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.

## 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}

# `json_type!`

```elixir
@spec json_type!(String.t() | map()) :: atom()
```

Detects the JSON graph format, raising on error for string input.

## Examples

    iex> json = ~s|{"elements": []}|
    iex> Yog.IO.JSON.json_type!(json)
    :cytoscape

# `to_cytoscape_json`

Quick export for Cytoscape.js with default settings.

# `to_d3_json`

Quick export for D3.js force-directed graphs with default settings.

# `to_json`

Converts a graph to a JSON string according to options.

# `to_json_file`

Exports a graph to a JSON file.

# `to_json_file_multi`

Exports a multigraph to a JSON file.

# `to_json_multi`

Converts a multigraph to a JSON string.

# `to_visjs_json`

Quick export for vis.js networks with default settings.

# `write`

Writes a graph to a JSON file using default export options.

# `write_with`

Writes a graph to a JSON file with custom export options.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
