Skip to main content

A modern Python library for formatting JSON Schema validation errors into ExceptionGroup trees.

Project description

tortoise-json-diagnostics

Python Version

A modern, highly customizable Python library for formatting JSON Schema validation errors into clear, human-readable code snippets and nested ExceptionGroup trees.


Key Features

  • 🌳 Nested ExceptionGroup Trees: Automatically groups flat jsonschema validation errors into structured hierarchy matching your JSON schema layout.
  • 🧩 Extensible Handler Pipeline: Allows custom error handlers to intercept, transform, and prune specific validation errors before fallback processing.
  • ⚙️ Global Formatter Registry: Easily switch or implement custom location and code snippet formatters (e.g., plain text, rich, ...).
  • 🐍 Modern Python Native: Built for modern Python with strict typing

Visual Output

Instead of unreadable raw validation objects, tortoise-json-diagnostics formats error groups like this:

  | ExceptionGroup: JSON Validation Error
  | File "input.json" (2 sub-exceptions)
  +-+---------------- 1 ----------------
    | ExceptionGroup: Property 'name'
    | File "input.json", line 1, column 2 (1 sub-exception)
    +-+---------------- 1 ----------------
      | tortoise_json_diagnostics.errors.JsonValidationError: 123 is not of type 'string'
      | File "input.json", line 1, column 10
      |    1 | {"name": 123, "age": -5}
      |                 ^^^
      +------------------------------------
    +---------------- 2 ----------------
    | ExceptionGroup: Property 'age'
    | File "input.json", line 1, column 15 (1 sub-exception)
    +-+---------------- 1 ----------------
      | tortoise_json_diagnostics.errors.JsonValidationError: -5 is less than the minimum of 0
      | File "input.json", line 1, column 22
      |    1 | {"name": 123, "age": -5}
      |                             ^^
      +------------------------------------

Installation

Using uv (recommended):

uv add json-diagnostics

Using pip:

pip install json-diagnostics

Quick Start

from jsonschema import Draft202012Validator
from tortoise_json_diagnostics import DiagnosticJsonParser

schema = {
    "type": "object",
    "required": ["name", "age"],
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer", "minimum": 0},
    },
}

validator = Draft202012Validator(schema)

parser = DiagnosticJsonParser(validator)

json_text = '{"name": 123, "age": -5}'
data = parser.parse_text(json_text, path="input.json")

Advanced Usage

Custom Error Handlers

You can intercept specific ValidationErrors before they hit the default handler by implementing IErrorHandler:

from tortoise_json_diagnostics import IErrorHandler, JsonValidationError

class CustomTypeMismatchHandler(IErrorHandler):
    def handle(self, validator, validation_errors, source_map, json_text, file_path, /):
        handled: list[JsonValidationError] = []
        unhandled = []

        for error in validation_errors:
            if error.validator == "type":
                message = f"[Type Mismatch] {error.message}"
                handled.append(JsonValidationError(message, validator, [error]))
            else:
                unhandled.append(error)

        return handled, unhandled

parser = DiagnosticJsonParser(validator, handlers=[CustomTypeMismatchHandler()])
  | ExceptionGroup: JSON Validation Error
  | File "input.json" (2 sub-exceptions)
  +-+---------------- 1 ----------------
    | ExceptionGroup: Property 'name'
    | File "input.json", line 1, column 2 (1 sub-exception)
    +-+---------------- 1 ----------------
      | json_diagnostics.errors.JsonValidationError: [Type Mismatch] 123 is not of type 'string'
      +------------------------------------
    +---------------- 2 ----------------
    | ExceptionGroup: Property 'age'
    | File "input.json", line 1, column 15 (1 sub-exception)
    +-+---------------- 1 ----------------
      | json_diagnostics.errors.JsonValidationError: -5 is less than the minimum of 0
      | File "input.json", line 1, column 22
      |    1 | {"name": 123, "age": -5}
      |                             ^^
      +------------------------------------

Global Formatters

Register custom formatters for file locations or text snippets:

from tortoise_json_diagnostics import LocationFormatter, set_global_location_formatter

class CompactLocationFormatter(LocationFormatter):
    def format(self, file_path, span, /) -> str:
        if not file_path:
            return ""
        if not span:
            return str(file_path)
        return f"{file_path}:{span.end.line + 1}:{span.end.column + 1}"

set_global_location_formatter(CompactLocationFormatter())
  | ExceptionGroup: JSON Validation Error
  | input.json (2 sub-exceptions)
  +-+---------------- 1 ----------------
    | ExceptionGroup: Property 'name'
    | input.json:1:8 (1 sub-exception)
    +-+---------------- 1 ----------------
      | json_diagnostics.errors.JsonValidationError: 123 is not of type 'string'
      | input.json:1:13
      |    1 | {"name": 123, "age": -5}
      |                 ^^^
      +------------------------------------
    +---------------- 2 ----------------
    | ExceptionGroup: Property 'age'
    | input.json:1:20 (1 sub-exception)
    +-+---------------- 1 ----------------
      | json_diagnostics.errors.JsonValidationError: -5 is less than the minimum of 0
      | input.json:1:24
      |    1 | {"name": 123, "age": -5}
      |                             ^^
      +------------------------------------

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tortoise_json_diagnostics-0.1.0.tar.gz (5.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tortoise_json_diagnostics-0.1.0-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file tortoise_json_diagnostics-0.1.0.tar.gz.

File metadata

File hashes

Hashes for tortoise_json_diagnostics-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cdb06b6b0130a9a5a9b0f32be832b4d03b2fc05d9697e3dad9b92f93c1ba41af
MD5 a88b16f27eefe94a17cb85cb3fdf3f84
BLAKE2b-256 6dc25b39835ccca76015f034858d9b64c9a86f45b8b8cc6783553844b9c564ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for tortoise_json_diagnostics-0.1.0.tar.gz:

Publisher: publish.yml on Testudinidae/tortoise-json-diagnostics

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tortoise_json_diagnostics-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for tortoise_json_diagnostics-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ea534dc94bd4a495278096269d1fa8f89c96f7b1584117fb6251fdcd44cdc154
MD5 6838ff17339a85ac721ab7720a36cb29
BLAKE2b-256 154f6c96aa317008c803441968b5f3e77114d2d92af41c54cd882c35826fb511

See more details on using hashes here.

Provenance

The following attestation bundles were made for tortoise_json_diagnostics-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Testudinidae/tortoise-json-diagnostics

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page