moon_json_repair

    Conservative JSON syntax repair with replayable edits and explicit refusal boundaries.

    json
    repair
    diagnostics
    llm
    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    20 hours ago
    Downloads
    3

    #Moon JSON Repair

    Conservative JSON syntax recovery with replayable edits. Pure MoonBit core, zero third-party package dependencies. A Node 24 CLI is included under cmd/main. No claim of full JSON5 or jsonrepair compatibility.

    #Consumer example

    After adding btlqql/moon_json_repair@0.1.0, import it in your moon.pkg:

    import { "btlqql/moon_json_repair" @repair, }

    ///|
    fn main {
    let result = try! @repair.repair("{name:'Moon',}")
    println(result.output)
    println(result.to_json().stringify())
    }

    The source repository contains this working example in examples/basic.

    #Public API

    • repair(input, options?) -> RepairResult raise RepairError
    • apply_edits(input, edits) -> String raise RepairError
    • repair_jsonl(input, options?, max_lines?) -> Array[LineResult] raise RepairError
    • Options::conservative() and Options::strict()

    RepairResult contains output and edits. An Edit has start/end (half-open UTF-16 offsets in the original input), replacement, and a stable code. Multiple insertions at the same position are applied in array order, inner container first. Replay validates ranges and refuses overlaps and surrogate-pair splitting. Edits are NOT bound cryptographically to their source; callers must retain and use the exact original input. Do not apply them to a different revision.

    Default limits: 1,048,576 UTF-16 code units, depth 128 (configurable 1..256), 10,000 edits, 10,000 JSONL lines. JSONL enforces the input limit on the whole batch. CLI additionally caps bytes read at 4 MiB and rejects malformed UTF-8. This implementation buffers input; it is not an unbounded streaming parser.

    relaxed enables bare ASCII identifier keys, single-quoted strings, comments, and trailing commas. close_containers defaults false and only works when relaxed mode is enabled. It can close containers after a complete value at EOF; it never completes strings, literals, empty containers, or values after commas. Missing middle commas/colons/values, duplicate keys, and extra root content fail. Numbers are not round-tripped through floating-point serialization.

    Failures raise Rejected(code, offset) without echoing source data. JSONL reports line-local offsets and one-based physical line numbers; a trailing newline is not an extra record. Blank interior lines fail. In JSON reports, absent optional fields are omitted: success has output, failure has error_code/error_offset.

    Repair success only establishes JSON syntax. It does not establish original intent, schema validity, authorization, or safe tool arguments. Review edits and validate schema and policy before consuming repaired data.

    License: Apache-2.0. See repository docs/provenance.md for design references, ecosystem overlap findings, and AI-assisted development disclosure.

    RepairError

    pub(all) suberror RepairError {
    Rejected(String, Int)
    } derive(Eq,
    Debug
    )

    Stable refusal code and original UTF-16 offset; no input data in errors.

    Edit

    pub(all) struct Edit {
    start : Int
    end : Int
    replacement : String
    code : String
    } derive(Eq, ToJson,
    Debug
    )

    An edit uses half-open UTF-16 offsets in the ORIGINAL input.

    LineResult

    pub(all) struct LineResult {
    line : Int
    output : String?
    edits : Array[Edit]
    error_code : String?
    error_offset : Int?
    } derive(Eq, ToJson,
    Debug
    )

    One JSONL line's result. Error offsets and edit ranges are line-local UTF-16.

    Options

    pub(all) struct Options {
    relaxed : Bool
    close_containers : Bool
    max_input : Int
    max_depth : Int
    max_edits : Int
    } derive(Eq,
    Debug
    )

    No heuristic is enabled in strict mode.

    Options::conservative

    fn Options::conservative() -> Options

    Options::strict

    fn Options::strict() -> Options

    RepairResult

    pub(all) struct RepairResult {
    output : String
    edits : Array[Edit]
    } derive(Eq, ToJson,
    Debug
    )

    Successful output is syntax-valid JSON, not schema-validated business data.

    apply_edits

    fn apply_edits(input : String, edits : Array[Edit]) -> String raise RepairError

    Replay ordered edits. Overlap, out-of-bounds and split-surrogate offsets fail.

    repair

    fn repair(input : String, options? : Options) -> RepairResult raise RepairError

    Valid input is preserved exactly, including number spelling and whitespace.

    repair_jsonl

    fn repair_jsonl(input : String, options? : Options, max_lines? : Int) -> Array[LineResult] raise RepairError

    Process each physical line independently; blank interior lines are errors. A final newline does not create a phantom record. Aggregate input is bounded.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io