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 tortoise-json-diagnostics

Using pip:

pip install tortoise-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.1.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.1-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for tortoise_json_diagnostics-0.1.1.tar.gz
Algorithm Hash digest
SHA256 aa0de06767b9a1f17af766c1615c2c970df12d96dc7f08cf3410aadfeeaf4fea
MD5 1ace873dc00ff2b825710b5bd7b423af
BLAKE2b-256 8788e1d74a607cd28e6ae8d3e3dbc8657f55005da63fbdc83fcfb3038ac11f6b

See more details on using hashes here.

Provenance

The following attestation bundles were made for tortoise_json_diagnostics-0.1.1.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.1-py3-none-any.whl.

File metadata

File hashes

Hashes for tortoise_json_diagnostics-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e6f103cf78a740f3b8fc459d9f0f0b984e8ae1564e5e00ecc629e931b76a8654
MD5 b79bcee1330e86c29bfc6e4b81da388c
BLAKE2b-256 c39a2ace16a5b2c24b19fe6f7f230d188d462987f6262726d070c07c224f02e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for tortoise_json_diagnostics-0.1.1-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