JsonRemedy (json_remedy v0.1.3)
View SourceA 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:
- 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"}, [
%{layer: :structural_repair, action: "added missing closing brace", position: 18, original: nil, replacement: "}"},
%{layer: :syntax_normalization, action: "quoted unquoted key", position: 1, original: nil, replacement: nil}
]}
Summary
Functions
Returns information about what repairs would be applied to the input.
Checks if a string appears to be malformed JSON that JsonRemedy can fix.
Repairs JSON content directly from a file.
Repairs malformed JSON and returns the parsed Elixir term.
Creates a stream that repairs JSON objects from an input stream.
Repairs malformed JSON and returns the fixed JSON string.
Repairs malformed JSON with detailed debugging information.
Types
@type json_value() :: nil | boolean() | number() | String.t() | [json_value()] | %{required(String.t()) => json_value()}
@type repair_result() :: {:ok, json_value()} | {:error, String.t()}
@type repair_result_with_logs() :: {:ok, json_value(), [repair_action()]} | {:error, String.t()}
Functions
@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}
]}
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
@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> JsonRemedy.from_file("config.json")
{:ok, %{"setting" => "value"}}
iex> JsonRemedy.from_file("nonexistent.json", logging: true)
{:error, "Could not read file: :enoent"}
@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 tupledebug: true
- Returns detailed step-by-step debugging informationjason_options: []
- Options to pass to Jason for final parsingfast_path_optimization: true
- Enable fast path for already valid JSON (default)
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}}
@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()
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}|}
@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