Receiving valid JSON does not mean a model has returned valid business data. A ticket label that your application cannot handle can still arrive inside perfectly parseable JSON.

What you will build

Build an executable validator for a ticket-classification result, rejecting unknown fields, incorrect types and unsupported labels.

Before you start

Python 3.10 or later; only the standard library is used. No model or API key is needed to run the tests.

1. Create validate_ticket.py

import json

def validate_ticket(raw: str) -> dict:
    value = json.loads(raw)
    if not isinstance(value, dict) or set(value) != {"label", "confidence"}:
        raise ValueError("Expected label and confidence only")
    if value["label"] not in ("billing", "technical", "other"):
        raise ValueError("Unknown label")
    confidence = value["confidence"]
    if type(confidence) not in (int, float) or not 0 <= confidence <= 1:
        raise ValueError("confidence must be a number between 0 and 1")
    return value

if __name__ == "__main__":
    good = '{"label":"technical","confidence":0.9}'
    print(validate_ticket(good))
    for bad in [
        '{"label":"refund","confidence":0.9}',
        '{"label":"billing","confidence":true}',
        '{"label":"other","confidence":2}',
        '{"label":"other","confidence":0.5,"command":"delete"}'
    ]:
        try:
            validate_ticket(bad)
            raise AssertionError("Invalid data was accepted")
        except ValueError:
            print("Rejected invalid result")

2. Run the example

python validate_ticket.py

Expected result

The valid dictionary is printed, followed by four Rejected invalid result lines.

How it works

This example separates parsing from validation. json.loads handles syntax; the remaining checks define the shape your own application accepts. Keep this boundary even when the model provider supports structured output.

The exact-key check rejects unexpected fields. In a more flexible public API you might deliberately allow optional fields, but that should be a documented decision. A strict boundary is convenient for small internal automation steps.

Python treats bool as a subclass of int. Using type(confidence) rather than a simple isinstance check prevents true from silently becoming a confidence score of one. The range comparison also rejects NaN and infinity.

Validation does not prove that the classification is correct. Use a human-reviewed test set and choose how uncertain cases should be handled before allowing classifications to trigger payments, account changes or other actions.

Test the edge cases

  • Add malformed JSON and confirm parsing fails.
  • Test confidence values of 0 and 1: both should be accepted.
  • Pass a JSON list or null: both should be rejected.

Keep learning

Browse related tutorials. Reference: official documentation.

Reviewed 7 November 2026. AI-dependent examples require your own local model; generated text varies.