# `JsonRemedy`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L1)

A blazingly fast, Elixir-native JSON repair library.

JsonRemedy uses a layered architecture with binary pattern matching to intelligently
repair malformed JSON strings while achieving superior performance.

This module provides the main API for JSON repair functionality. It supports
multiple repair strategies and can handle various types of malformed JSON through
a four-layer processing pipeline with intelligent preprocessing:

- **Preprocessing**: Multiple JSON detection (Pattern 1)
- **Layer 1**: Content Cleaning (removes code fences, comments, extra text)
- **Layer 2**: Structural Repair (fixes missing braces, brackets, etc.)
- **Layer 3**: Syntax Normalization (quotes, booleans, commas, colons)
- **Layer 4**: Validation (validates and parses the final JSON)

## Examples

    iex> JsonRemedy.repair(~s|{name: "Alice", age: 30, active: True}|)
    {:ok, %{"name" => "Alice", "age" => 30, "active" => true}}

    iex> JsonRemedy.repair_to_string(~s|[1, 2, 3,]|)
    {:ok, "[1,2,3]"}

    iex> JsonRemedy.repair(~s|{incomplete: "data"|, logging: true)
    {:ok, %{"incomplete" => "data"}, [
      %{position: 18, action: "added missing closing brace", original: nil, layer: :structural_repair, replacement: "}"},
      %{position: 1, action: "quoted unquoted key", original: nil, layer: :syntax_normalization, replacement: nil}
    ]}

# `json_value`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L45)

```elixir
@type json_value() ::
  nil
  | boolean()
  | number()
  | String.t()
  | [json_value()]
  | %{required(String.t()) =&gt; json_value()}
```

# `option`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L50)

```elixir
@type option() ::
  {:logging, boolean()}
  | {:debug, boolean()}
  | {:jason_options, keyword()}
  | {:fast_path_optimization, boolean()}
  | {:strict_mode, boolean()}
```

# `repair_action`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L47)

```elixir
@type repair_action() :: %{layer: atom(), action: String.t()}
```

# `repair_result`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L48)

```elixir
@type repair_result() :: {:ok, json_value()} | {:error, String.t()}
```

# `repair_result_with_logs`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L49)

```elixir
@type repair_result_with_logs() ::
  {:ok, json_value(), [repair_action()]} | {:error, String.t()}
```

# `analyze`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L258)

```elixir
@spec analyze(binary()) :: {:ok, [repair_action()]} | {:error, String.t()}
```

Returns information about what repairs would be applied to the input.

Processes through the pipeline but returns detailed information about what
each layer would do without actually applying the repairs.

## Examples

    iex> JsonRemedy.analyze(~s|{name: 'Alice', active: True}|)
    {:ok, [
      %{layer: :syntax_normalization, action: "normalized boolean", position: 24, original: nil, replacement: nil},
      %{layer: :syntax_normalization, action: "quoted unquoted key", position: 16, original: nil, replacement: nil},
      %{layer: :syntax_normalization, action: "normalized quotes", position: 7, original: nil, replacement: nil},
      %{layer: :syntax_normalization, action: "quoted unquoted key", position: 1, original: nil, replacement: nil}
    ]}

# `can_repair?`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L235)

```elixir
@spec can_repair?(binary()) :: boolean()
```

Checks if a string appears to be malformed JSON that JsonRemedy can fix.

Returns `true` if the input has issues that JsonRemedy layers can address.

## Examples

    iex> JsonRemedy.can_repair?(~s|{"valid": true}|)
    false

    iex> JsonRemedy.can_repair?(~s|{name: "Alice"}|)
    true

    iex> JsonRemedy.can_repair?(~s/```json\n{"test": true}\n```/)
    true

# `from_file`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L182)

```elixir
@spec from_file(Path.t(), [option()]) :: repair_result() | repair_result_with_logs()
```

Repairs JSON content directly from a file.

Reads the file and processes it through the JsonRemedy pipeline.

## Examples

    iex> {:ok, result} = JsonRemedy.from_file("test/data/invalid.json")
    iex> is_list(result)
    true

    iex> JsonRemedy.from_file("nonexistent.json", logging: true)
    {:error, "Could not read file: :enoent"}

# `repair`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L86)

```elixir
@spec repair(binary(), [option()]) :: repair_result() | repair_result_with_logs()
```

Repairs malformed JSON and returns the parsed Elixir term.

Processes the input through all four layers of the JsonRemedy pipeline to fix
common JSON formatting issues and return a parsed Elixir data structure.

## Options

- `logging: true` - Returns repair actions taken as third element in tuple
- `debug: true` - Returns detailed step-by-step debugging information
- `jason_options: []` - Options to pass to Jason for final parsing
- `fast_path_optimization: true` - Enable fast path for already valid JSON (default)
- `strict_mode: true` - Validate only; do not repair malformed JSON

## Examples

    iex> JsonRemedy.repair(~s|{"name": "John", "age": 30}|)
    {:ok, %{"name" => "John", "age" => 30}}

    iex> JsonRemedy.repair(~s|{name: "John", age: 30, active: True}|)
    {:ok, %{"name" => "John", "age" => 30, "active" => true}}

    iex> JsonRemedy.repair(~s|[1, 2, 3,]|, logging: true)
    {:ok, [1, 2, 3], [%{layer: :syntax_normalization, action: "removed trailing comma", position: 8, original: nil, replacement: nil}]}

    iex> JsonRemedy.repair(~s/```json\n{"valid": true}\n```/)
    {:ok, %{"valid" => true}}

# `repair_stream`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L204)

```elixir
@spec repair_stream(Enumerable.t(), [option()]) :: Enumerable.t()
```

Creates a stream that repairs JSON objects from an input stream.

Useful for processing large files or real-time data streams. Each item in the
stream is processed independently through the JsonRemedy pipeline.

## Examples

    "large_file.jsonl"
    |> File.stream!()
    |> JsonRemedy.repair_stream()
    |> Stream.each(&IO.inspect/1)
    |> Stream.run()

# `repair_to_string`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L152)

```elixir
@spec repair_to_string(binary(), [option()]) :: {:ok, binary()} | {:error, String.t()}
```

Repairs malformed JSON and returns the fixed JSON string.

Like `repair/2`, but returns the repaired JSON as a string rather than parsing it.

## Examples

    iex> JsonRemedy.repair_to_string(~s|{name: "Alice"}|)
    {:ok, ~s|{"name":"Alice"}|}

    iex> JsonRemedy.repair_to_string(~s|[1, 2, 3,]|)
    {:ok, "[1,2,3]"}

    iex> JsonRemedy.repair_to_string(~s/```json\n{"test": true}\n```/)
    {:ok, ~s|{"test":true}|}

# `repair_with_debug`
[🔗](https://github.com/nshkrdotcom/json_remedy/blob/v0.2.1/lib/json_remedy.ex#L297)

```elixir
@spec repair_with_debug(binary(), [option()]) ::
  {:ok, json_value(),
   %{
     steps: [map()],
     total_repairs: non_neg_integer(),
     processing_time_us: non_neg_integer()
   }}
  | {:error, String.t(),
     %{
       steps: [map()],
       total_repairs: non_neg_integer(),
       processing_time_us: non_neg_integer()
     }}
```

Repairs malformed JSON with detailed debugging information.

Returns comprehensive information about each step of the repair process,
including what each layer attempted to do and why it succeeded or failed.

## Examples

    iex> {:ok, result, debug} = JsonRemedy.repair_with_debug(~s|{name: 'Alice', active: True}|)
    iex> result
    %{"name" => "Alice", "active" => true}
    iex> debug.total_repairs
    4
    iex> length(debug.steps)
    4

---

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