Repair malformed JSON from LLMs, APIs, logs, and user input in Python.
This report summarizes scanner evidence for mangiucugna/json_repair, a Python project with 5,117 GitHub stars. SynthScan examined 13,424 lines of code across 80 source files, recording 416 pattern matches distributed across 12 syntactic categories. The legacy adjusted pattern signal is 37.0 (High pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 365 finding(s).
Are imports declared and package/API names verified? 40 finding(s).
Are wrappers, guards, and repeated structures necessary? 345 finding(s).
Which changes need focused human review? 416 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 416 distinct pattern matches across 12 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_parse_comment.py | 24 | def test_line_comment_brackets_do_not_trigger_empty_object_array_fallback(): | CODE |
| LOW⚡ | tests/test_parse_comment.py | 31 | def test_block_comment_brackets_do_not_trigger_empty_object_array_fallback(): | CODE |
| LOW⚡ | tests/test_parse_comment.py | 38 | def test_line_comment_brackets_do_not_close_array_items(): | CODE |
| LOW | tests/test_parse_comment.py | 63 | def test_parse_many_top_level_comments_without_recursion_error(): | STRING |
| LOW | tests/test_docs_app_schema.py | 15 | def test_docs_api_without_schema_keeps_existing_behavior(client): | CODE |
| LOW | tests/test_docs_app_schema.py | 26 | def test_docs_api_schema_null_is_treated_as_missing(client): | CODE |
| LOW | tests/test_docs_app_schema.py | 37 | def test_docs_api_schema_guides_coercion(client): | CODE |
| LOW | tests/test_docs_app_schema.py | 58 | def test_docs_api_rejects_invalid_schema_type(client): | CODE |
| LOW | tests/test_docs_app_schema.py | 85 | def test_docs_api_rejects_circular_schema_ref(client): | CODE |
| LOW⚡ | tests/test_docs_app_schema.py | 103 | def test_docs_api_rejects_invalid_schema_repair_mode_type(client): | CODE |
| LOW⚡ | tests/test_docs_app_schema.py | 113 | def test_docs_api_rejects_invalid_schema_repair_mode_value(client): | CODE |
| LOW⚡ | tests/test_docs_app_schema.py | 123 | def test_docs_api_rejects_salvage_mode_without_schema(client): | CODE |
| LOW⚡ | tests/test_docs_app_schema.py | 133 | def test_docs_api_salvage_mode_drops_invalid_array_items(client): | CODE |
| LOW⚡ | tests/test_parse_number.py | 25 | def test_parse_number_positive_exponent(raw, expected, skip_json_loads): | CODE |
| LOW⚡ | tests/test_parse_number.py | 30 | def test_parse_number_plus_outside_exponent(): | CODE |
| LOW⚡ | tests/test_parse_number.py | 35 | def test_parse_number_edge_cases(): | CODE |
| LOW | tests/test_parse_number.py | 60 | def test_numeric_prefix_identifiers_preserve_underscored_digits(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 27 | def test_missing_opening_object_brace(raw, expected, skip_json_loads): | CODE |
| LOW⚡ | tests/test_json_repair.py | 31 | def test_missing_opening_object_brace_logs_and_serializes(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 58 | def test_missing_opening_brace_declines_other_malformed_inputs(raw, expected, skip_json_loads): | CODE |
| LOW⚡ | tests/test_json_repair.py | 66 | def test_missing_opening_brace_declines_integer_conversion_limit(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 74 | def test_valid_top_level_string_preserved_with_strict_mode(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 116 | def test_valid_json_fast_path_does_not_initialize_repair_parser(monkeypatch): | CODE |
| LOW⚡ | tests/test_json_repair.py | 117 | def fail_parser_initialization(*_args, **_kwargs): | CODE |
| LOW⚡ | tests/test_json_repair.py | 125 | def test_skip_json_loads_does_not_raw_decode_complete_json(monkeypatch): | CODE |
| LOW⚡ | tests/test_json_repair.py | 134 | def test_prefixed_valid_json_uses_value_fast_path_when_json_loads_is_skipped(monkeypatch): | CODE |
| LOW⚡ | tests/test_json_repair.py | 200 | def test_top_level_separator_detects_pending_comma(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 206 | def test_initial_container_trailing_content_rejects_mismatched_delimiters(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 212 | def test_parenthesized_prose_does_not_hijack_fenced_json(): | CODE |
| LOW⚡ | tests/test_json_repair.py | 349 | def test_repair_json_skip_json_loads(): | CODE |
| LOW | tests/test_json_repair.py | 90 | def test_no_speculative_decode_without_missing_brace_signal(raw, expected, monkeypatch): | CODE |
| LOW | tests/test_json_repair.py | 159 | def test_prefixed_valid_json_with_trailing_text_uses_value_fast_path(monkeypatch): | CODE |
| LOW | tests/test_json_repair.py | 171 | def test_valid_json_with_trailing_garbage_preserves_string_content(skip_json_loads): | CODE |
| LOW | tests/test_json_repair.py | 181 | def test_prefixed_invalid_json_falls_back_to_repair_parser(): | CODE |
| LOW | tests/test_json_repair.py | 229 | def test_numbered_prose_line_does_not_hijack_fenced_json(): | CODE |
| LOW | tests/test_json_repair.py | 246 | def test_parenthesized_tuple_still_parses_when_it_is_the_fenced_json_payload(): | CODE |
| LOW | tests/test_json_repair.py | 259 | def test_repair_json_with_objects(): | CODE |
| LOW | tests/test_json_repair.py | 374 | def _find_real_recursion_payload() -> str: | CODE |
| LOW | tests/test_json_repair.py | 390 | def test_repair_json_normalizes_real_parser_recursion_error(): | CODE |
| LOW | tests/test_repair_json_from_file.py | 12 | def test_load_repairs_missing_opening_brace_from_current_position(skip_json_loads): | CODE |
| LOW⚡ | tests/test_repair_json_from_file.py | 23 | def test_load_declines_missing_opening_brace_with_trailing_content(): | CODE |
| LOW⚡ | tests/test_repair_json_from_file.py | 27 | def test_load_strict_rejects_missing_opening_brace(): | CODE |
| LOW⚡ | tests/test_repair_json_from_file.py | 32 | def test_load_repairs_from_current_file_position(): | CODE |
| LOW | tests/test_repair_json_from_file.py | 43 | def test_repair_json_from_file(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 8 | def test_strict_rejects_missing_opening_object_brace(raw, skip_json_loads): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 13 | def test_strict_rejects_multiple_top_level_values(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 18 | def test_strict_rejects_comma_separated_same_shape_top_level_objects(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 23 | def test_strict_rejects_adjacent_same_shape_top_level_objects(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 28 | def test_strict_rejects_adjacent_same_shape_top_level_arrays(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 34 | def test_strict_rejects_falsy_top_level_values(payload): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 39 | def test_strict_duplicate_keys_inside_array(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 45 | def test_strict_rejects_empty_keys(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 51 | def test_strict_requires_colon_between_key_and_value(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 56 | def test_strict_rejects_empty_values(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 62 | def test_strict_rejects_empty_object_with_extra_characters(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 67 | def test_strict_rejects_empty_escaped_object_with_extra_characters(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 72 | def test_strict_detects_immediate_doubled_quotes(): | CODE |
| LOW⚡ | tests/test_strict_mode.py | 77 | def test_strict_detects_doubled_quotes_followed_by_string(): | CODE |
| LOW | tests/test_parse_array.py | 12 | def test_parse_array_edge_cases(): | CODE |
| LOW⚡ | tests/test_parse_array.py | 53 | def test_parse_array_closes_before_object_member_after_scalar_items(): | CODE |
| 269 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | tests/test_json_repair.py | 20 | ('"a": 0, "b": false, "c": null, "d": ""}', {"a": 0, "b": False, "c": None, "d": ""}), | CODE |
| HIGH⚡ | tests/test_json_repair.py | 351 | repair_json('{"key": true, "key2": false, "key3": null}', skip_json_loads=True) | CODE |
| HIGH⚡ | tests/test_json_repair.py | 352 | == '{"key": true, "key2": false, "key3": null}' | CODE |
| HIGH⚡ | tests/test_json_repair.py | 355 | '{"key": true, "key2": false, "key3": null}', | CODE |
| HIGH | tests/test_json_repair.py | 263 | assert repair_json('{"key": true, "key2": false, "key3": null}', return_objects=True) == { | CODE |
| HIGH | tests/test_parse_array.py | 21 | assert repair_json("[true, false, null, ...]") == "[true, false, null]" | CODE |
| HIGH⚡ | tests/test_parse_array.py | 77 | assert repair_json("(true, false, null)", return_objects=True, skip_json_loads=True) == [True, False, None] | CODE |
| HIGH | tests/test_parse_object.py | 12 | assert repair_json('{ "key": value, "key2": 1 "key3": null }', return_objects=True) == { | CODE |
| HIGH⚡ | tests/test_parse_string.py | 46 | repair_json("{'key': 'string', 'key2': false, \"key3\": null, \"key4\": unquoted}") | CODE |
| HIGH⚡ | tests/test_parse_string.py | 47 | == '{"key": "string", "key2": false, "key3": null, "key4": "unquoted"}' | CODE |
| HIGH⚡ | tests/test_parse_string.py | 403 | assert repair_json(' {"key": true, "key2": false, "key3": null}') == '{"key": true, "key2": false, "key3": null}' | STRING |
| HIGH⚡ | tests/test_parse_string.py | 404 | assert repair_json('{"key": TRUE, "key2": FALSE, "key3": Null} ') == '{"key": true, "key2": false, "key3": null}' | STRING |
| HIGH | tests/test_schema_guided_parse.py | 714 | == '{"a": null, "b": null}' | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/json_repair/parse_array.py | 12 | CODE | |
| LOW | src/json_repair/parse_array.py | 41 | CODE | |
| LOW | src/json_repair/parse_comment.py | 10 | CODE | |
| LOW | src/json_repair/parser_parenthesized.py | 9 | CODE | |
| LOW | src/json_repair/parser_parenthesized.py | 82 | CODE | |
| LOW | src/json_repair/schema_repair.py | 45 | CODE | |
| LOW | src/json_repair/schema_repair.py | 91 | CODE | |
| LOW | src/json_repair/schema_repair.py | 365 | CODE | |
| LOW | src/json_repair/parse_string.py | 56 | CODE | |
| LOW | src/json_repair/parse_string.py | 116 | CODE | |
| LOW | src/json_repair/parse_string.py | 143 | CODE | |
| LOW | src/json_repair/parse_string.py | 185 | CODE | |
| LOW | src/json_repair/parse_string.py | 450 | CODE | |
| LOW | src/json_repair/parse_string.py | 480 | CODE | |
| LOW | src/json_repair/parse_string.py | 552 | CODE | |
| LOW | src/json_repair/parse_string.py | 676 | CODE | |
| LOW | src/json_repair/json_repair.py | 100 | CODE | |
| LOW | src/json_repair/parse_object.py | 82 | CODE | |
| LOW | src/json_repair/parse_object.py | 132 | CODE | |
| LOW | src/json_repair/parse_object.py | 181 | CODE | |
| LOW | src/json_repair/parse_object.py | 379 | CODE | |
| LOW | src/json_repair/json_parser.py | 143 | CODE | |
| LOW | src/json_repair/json_parser.py | 188 | CODE | |
| LOW | …n_repair/parse_string_helpers/parse_boolean_or_null.py | 15 | CODE | |
| LOW | src/json_repair/utils/pattern_properties.py | 7 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | examples/pydantic_schema.py | 3 | CODE | |
| LOW | examples/stream_stable.py | 3 | CODE | |
| LOW | examples/repair_llm_output.py | 3 | CODE | |
| LOW | examples/chinese_llm_output.py | 3 | CODE | |
| LOW | examples/fastapi_app.py | 3 | CODE | |
| LOW | src/json_repair/parse_array.py | 9 | CODE | |
| LOW | src/json_repair/parse_comment.py | 7 | CODE | |
| LOW | src/json_repair/parser_parenthesized.py | 6 | CODE | |
| LOW | src/json_repair/schema_repair.py | 1 | CODE | |
| LOW | src/json_repair/parse_string.py | 11 | CODE | |
| LOW | src/json_repair/__init__.py | 1 | CODE | |
| LOW | src/json_repair/__init__.py | 1 | CODE | |
| LOW | src/json_repair/__init__.py | 1 | CODE | |
| LOW | src/json_repair/__init__.py | 1 | CODE | |
| LOW | src/json_repair/__init__.py | 2 | CODE | |
| LOW | src/json_repair/parse_object.py | 9 | CODE | |
| LOW | src/json_repair/parse_object.py | 10 | CODE | |
| LOW | src/json_repair/parse_number.py | 10 | CODE | |
| LOW | src/json_repair/parser_schema.py | 1 | CODE | |
| LOW | …on_repair/parse_string_helpers/parse_json_llm_block.py | 6 | CODE | |
| LOW | …on_repair/parse_string_helpers/object_value_context.py | 7 | CODE | |
| LOW | …n_repair/parse_string_helpers/parse_boolean_or_null.py | 4 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/json_repair/json_repair.py | 188 | except (json.JSONDecodeError, TypeError, ValueError): | CODE |
| HIGH | src/json_repair/json_repair.py | 182 | except ValueError: | CODE |
| HIGH | src/json_repair/json_parser.py | 406 | except IndexError: | CODE |
| HIGH | src/json_repair/json_parser.py | 420 | except IndexError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | src/json_repair/json_repair.py | 425 | print("Error: Inline mode requires a filename", file=sys.stderr) | CODE |
| MEDIUM⚡ | src/json_repair/json_repair.py | 429 | print("Error: You cannot pass both --inline and --output", file=sys.stderr) | CODE |
| MEDIUM⚡ | src/json_repair/json_repair.py | 433 | print("Error: You cannot pass both --schema and --schema-model", file=sys.stderr) | CODE |
| MEDIUM⚡ | src/json_repair/json_repair.py | 437 | print("Error: --strict cannot be used with --schema or --schema-model", file=sys.stderr) | CODE |
| MEDIUM⚡ | src/json_repair/json_repair.py | 440 | print("Error: --schema-repair-mode salvage requires --schema or --schema-model", file=sys.stderr) | CODE |
| MEDIUM | src/json_repair/json_repair.py | 477 | print(f"Error: {e!s}", file=sys.stderr) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_repair_json_from_file.py | 452 | # Create a temporary file | COMMENT |
| MEDIUM | tests/test_repair_json_from_file.py | 520 | # Create a temporary file | COMMENT |
| MEDIUM | tests/test_repair_json_cli.py | 14 | # Create a temporary file | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_parse_array.py | 123 | repair_json('{"bad_one":["Lorem Ipsum", "consectetur" comment" ], "good_one":[ "elit", "sed", "tempor"]}') | CODE |
| LOW⚡ | tests/test_parse_array.py | 124 | == '{"bad_one": ["Lorem Ipsum", "consectetur", "comment"], "good_one": ["elit", "sed", "tempor"]}' | CODE |
| LOW⚡ | tests/test_parse_array.py | 127 | repair_json('{"bad_one": ["Lorem Ipsum","consectetur" comment],"good_one": ["elit","sed","tempor"]}') | CODE |
| LOW⚡ | tests/test_parse_array.py | 128 | == '{"bad_one": ["Lorem Ipsum", "consectetur", "comment"], "good_one": ["elit", "sed", "tempor"]}' | CODE |
| LOW | tests/test_parse_string.py | 82 | repair_json('{"key": "lorem ipsum ... "sic " tamet. ...}') == '{"key": "lorem ipsum ... \\"sic \\" tamet. ..."}' | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/json_repair/json_repair.py | 339 | Command-line interface for repairing and parsing JSON files. Args: inline_args (Optional[List[str]]): | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/json_repair/json_repair.py | 37 | CODE | |
| LOW | src/json_repair/json_repair.py | 53 | CODE | |
| LOW | src/json_repair/json_repair.py | 69 | CODE | |
| LOW | src/json_repair/json_repair.py | 85 | CODE | |
| LOW | src/json_repair/json_repair.py | 100 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pyproject.toml | 81 | [project.scripts] | COMMENT |
| LOW | pyproject.toml | 101 | # Flake8-commas - COM | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/json_repair/__init__.py | 4 | __all__ = ["JSONReturnType", "from_file", "load", "loads", "repair_json"] | CODE |