| Crates.io | jsonrepair |
| lib.rs | jsonrepair |
| version | 0.1.0 |
| created_at | 2025-10-21 08:33:38.582762+00 |
| updated_at | 2025-10-21 08:33:38.582762+00 |
| description | Fast, low-dependency JSON repair for Rust. Turns 'almost JSON' into valid JSON; supports streaming and writer-based output. |
| homepage | https://github.com/Latias94/jsonrepair |
| repository | https://github.com/Latias94/jsonrepair |
| max_upload_size | |
| id | 1893435 |
| size | 340,180 |
A fast, low-dependency JSON repair library for Rust. Fixes malformed JSON commonly produced by LLMs and other sources.
serde_json::Value (like Python's json.loads())jsonrepair / jr)[dependencies]
jsonrepair = "0.1"
use jsonrepair::{repair_json, Options};
let broken = "{name: 'John', age: 30,}";
let fixed = repair_json(broken, &Options::default())?;
// Result: {"name":"John","age":30}
use jsonrepair::loads;
let value = loads("{a: 1, b: 'hello'}", &Options::default())?;
assert_eq!(value["a"], 1);
use jsonrepair::StreamRepairer;
let mut repairer = StreamRepairer::new(Options::default());
for chunk in chunks {
if let Some(output) = repairer.push(chunk)? {
// Process output
}
}
if let Some(final_output) = repairer.flush()? {
// Process final output
}
use jsonrepair::from_file;
let value = from_file("broken.json", &Options::default())?;
//, /* ... */, # (optional)json ... ), JSONP (callback(...))"a" + "b" → "ab"/pattern/ → "/pattern/"True/False/None, JavaScript undefinedNaN/Infinity → null, leading zeros handling// Repair to string
repair_json(input: &str, opts: &Options) -> Result<String>
// Parse to Value (requires 'serde' feature)
loads(input: &str, opts: &Options) -> Result<serde_json::Value>
load(reader: impl Read, opts: &Options) -> Result<serde_json::Value>
from_file(path: impl AsRef<Path>, opts: &Options) -> Result<serde_json::Value>
// Write to writer
repair_to_writer(input: &str, opts: &Options, writer: &mut impl Write)
let mut repairer = StreamRepairer::new(opts);
repairer.push(chunk: &str) -> Result<Option<String>>
repairer.flush() -> Result<Option<String>>
// Writer variants
repairer.push_to_writer(chunk: &str, writer: &mut impl Write)
repairer.flush_to_writer(writer: &mut impl Write)
Options {
tolerate_hash_comments: bool, // Allow # comments (default: true)
repair_undefined: bool, // undefined → null (default: true)
allow_python_keywords: bool, // True/False/None (default: true)
normalize_js_nonfinite: bool, // NaN/Infinity → null (default: true)
fenced_code_blocks: bool, // Strip ``` fences (default: true)
stream_ndjson_aggregate: bool, // Aggregate NDJSON (default: false)
leading_zero_policy: LeadingZeroPolicy, // KeepAsNumber | QuoteAsString
ensure_ascii: bool, // Escape non-ASCII (default: false)
logging: bool, // Enable repair log (default: false)
// ... more options in docs
}
Install:
cargo install jsonrepair
Basic usage:
# From file
jsonrepair input.json -o output.json
# From stdin
echo "{a: 1}" | jsonrepair
# In-place edit
jsonrepair --in-place broken.json
# Streaming mode (low memory)
jsonrepair --stream large_file.json
# Pretty print
jsonrepair --pretty input.json
Options:
-o, --output FILE Output file (default: stdout)
--in-place Overwrite input file
--stream Streaming mode (low memory)
--ndjson-aggregate Aggregate NDJSON into array
--pretty Pretty-print output
--ensure-ascii Escape non-ASCII characters
--no-python-keywords Disable Python keyword normalization
--no-undefined-null Disable undefined → null
--no-fence Disable fence stripping
--no-hash-comments Disable # comments
Native Python bindings using PyO3:
pip install jsonrepair
import jsonrepair
# Repair and parse
data = jsonrepair.loads("{name: 'John', age: 30}")
# {'name': 'John', 'age': 30}
# Just repair, return string
fixed = jsonrepair.repair_json("{a: 1}")
# '{"a":1}'
# Load from file
data = jsonrepair.from_file('broken.json')
# Streaming API
repairer = jsonrepair.StreamRepairer()
for chunk in chunks:
if output := repairer.push(chunk):
process(output)
if final := repairer.flush():
process(final)
See python/ for complete documentation and examples.
Build with C API:
cargo build --release --features c-api
This generates:
include/jsonrepair.htarget/release/libjsonrepair.{so,dylib,dll}Example:
#include "jsonrepair.h"
char* fixed = jsonrepair_repair("{a:1}");
printf("%s
", fixed); // {"a":1}
jsonrepair_free(fixed);
See examples/c_example for complete examples.
// #cgo LDFLAGS: -L./target/release -ljsonrepair
// #include "include/jsonrepair.h"
import "C"
result := C.jsonrepair_repair(C.CString("{a:1}"))
defer C.jsonrepair_free(result)
fmt.Println(C.GoString(result))
See examples/go_example for complete examples.
The C API works with any language supporting C FFI:
This library uses a zero-copy architecture (hand-written recursive descent parser with &str slicing) optimized for:
For NDJSON streams or heavily commented small objects, consider llm_json which uses a different architecture optimized for those patterns.
Run benchmarks:
python scripts/run_benchmarks.py
This project is inspired by and aims to be compatible with json_repair by Stefano Baccianella. We're grateful for the excellent design and comprehensive test suite that made this implementation possible.
MIT or Apache-2.0