Skip to content

Validator — validate_schema()

The validator module checks SDF data.json payloads against their schema.json and validates meta.json field structure. Validation is synchronous, offline, and raises no network requests.

Import

from sdf import validate_schema, validate_meta

validate_schema(data, schema)

Validates a data dict against a JSON Schema Draft 2020-12 schema.

validate_schema(data: dict, schema: dict) -> ValidationResult
ParameterTypeDescription
datadictThe data.json payload to validate
schemadictJSON Schema Draft 2020-12

Returns: ValidationResult

Does not raise on validation failure — use the valid field on the returned object to check the result.

ValidationResult

@dataclass
class ValidationResult:
valid: bool
errors: list[ValidationError]
@dataclass
class ValidationError:
path: str # JSON pointer to the failing field
message: str # Human-readable error message
schema_path: str # Path within the schema that triggered the error

Basic usage

validator-basic.py
from sdf import validate_schema
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["invoice_number", "total"],
"properties": {
"invoice_number": {"type": "string"},
"total": {
"type": "object",
"required": ["amount", "currency"],
"properties": {
"amount": {"type": "string"},
"currency": {"type": "string", "pattern": "^[A-Z]{3}$"},
},
},
},
}
data = {
"invoice_number": "INV-2026-001",
"total": {"amount": "1250.00", "currency": "EUR"},
}
result = validate_schema(data, schema)
if result.valid:
print("Document is valid")
else:
for error in result.errors:
print(f" {error.path}: {error.message}")

Handling validation errors

validator-errors.py
from sdf import validate_schema
# Missing required field and wrong currency format
data = {
"total": {"amount": "1250.00", "currency": "eur"}, # lowercase — fails pattern
}
result = validate_schema(data, schema)
print(result.valid) # False
print(len(result.errors)) # 2
for error in result.errors:
print(f"Path: {error.path}")
print(f" {error.message}")
# Path: /invoice_number
# 'invoice_number' is a required property
# Path: /total/currency
# 'eur' does not match '^[A-Z]{3}$'

Validating a parsed SDF document

After reading a document with parse_sdf(), validate data against the embedded schema:

validate-parsed.py
from sdf import parse_sdf, validate_schema
from sdf.errors import SDFError
with open("invoice.sdf", "rb") as f:
result = parse_sdf(f.read())
validation = validate_schema(result.data, result.schema)
if not validation.valid:
raise SDFError(
"SDF_ERROR_SCHEMA_MISMATCH",
f"Document data does not satisfy its embedded schema: "
+ "; ".join(f"{e.path}: {e.message}" for e in validation.errors),
)
print("Document data is valid")

validate_meta(meta)

Validates an SDFMeta object for required fields and correct value formats.

validate_meta(meta: SDFMeta) -> None

Raises: SDFError with code SDF_ERROR_INVALID_META if any required field is missing or malformed.

validate-meta.py
from sdf import SDFMeta, validate_meta
from sdf.errors import SDFError
meta = SDFMeta(
issuer="Acme Corp",
issuer_id="DE123456789",
document_type="invoice",
)
try:
validate_meta(meta)
print("Meta is valid")
except SDFError as e:
print(f"Invalid meta: {e}")

validate_meta() checks:

  • issuer is non-empty
  • document_type is non-empty
  • document_id is a valid UUID v4 (auto-generated by SDFMeta, so this will always pass unless manually overridden)
  • sdf_version is a supported version string
  • issued_at is a valid ISO 8601 datetime string (auto-generated, always passes unless manually overridden)

Offline operation

All validation uses the schema.json embedded inside the .sdf archive. External $ref URIs in schemas are not fetched. If a schema references an external URL, validation will fail with a schema compilation error — not silently succeed.

This is intentional: SDF documents must be fully self-validating. A document produced today must be validatable 20 years from now without any network access.