apischema: JSON (de)serialization, GraphQL, and JSON Schema
apischema is a Python library for JSON (de)serialization, GraphQL, and JSON schema generation, heavily leveraging Python's type hints. It is currently at version 0.19.0 and maintains an active release cadence with frequent updates and bug fixes.
Common errors
-
TypeError: 'type' object is not subscriptable
cause Using type hints like `list[str]` or `dict[str, int]` on Python versions older than 3.9, or when `typing-extensions` is not installed on Python 3.8 where it might be needed.fixEnsure your Python version is 3.9 or newer. If on Python 3.8, ensure `typing-extensions` is installed and updated (`pip install 'typing-extensions>=4.0'`). Alternatively, use `typing.List[str]` syntax for older Python versions. -
apischema.validation.errors.ValidationError: [path]: error message
cause Input data does not conform to the type annotations or validation rules defined in the Python type. This is `apischema`'s way of reporting schema mismatches.fixExamine the error message to identify the field (`[path]`) and the expected type/format. Adjust the input data to match the Python type definition, or refine the type definition to correctly represent the expected data. -
ImportError: cannot import name 'schema_json' from 'apischema'
cause The `schema_json` function was relocated to `apischema.json_schema.schema_json_from_obj` in newer versions.fixChange your import statement from `from apischema import schema_json` to `from apischema.json_schema import schema_json_from_obj`. -
TypeError: 'ApischemaSettings' object is not callable
cause In older versions, `apischema.settings` was sometimes used as a callable. In newer versions (e.g., v0.18.0+), `apischema.settings` is an object, and configuration is done through `apischema.confs` or by directly setting attributes on the `apischema.settings` object.fixIf configuring global settings, use `apischema.confs.set_deserialization_coercion(True)` or similar methods, or directly modify attributes like `apischema.settings.deserialization.coercion = True`. Do not treat `apischema.settings` as a function.
Warnings
- breaking Python 3.7 support was dropped in v0.18.2. Users on Python 3.7 or older must upgrade their Python environment to at least 3.9 (as per current PyPI `requires_python`) to use recent versions of apischema.
- breaking Various deprecated APIs were removed in v0.18.0. Code relying on functions or classes marked as deprecated in earlier versions will break.
- breaking Since v0.17.0, arbitrary exceptions raised during serialization are no longer automatically converted to `ValidationError`. This change enhances security by preventing unexpected exception type conversion.
- gotcha When defining dataclasses, using `apischema.dataclasses.dataclass` is often preferred over `dataclasses.dataclass` (from the standard library) for full feature integration.
Install
-
pip install apischema -
pip install apischema[graphql] -
pip install apischema[validation]
Imports
- serialize
from apischema import serialize
- deserialize
from apischema import deserialize
- schema
from apischema import schema
- schema_json_from_obj
from apischema import schema_json
from apischema.json_schema import schema_json_from_obj
- ValidationError
from apischema.validation.errors import ValidationError
- dataclass
from dataclasses import dataclass # (potentially less features)
from apischema.dataclasses import dataclass
Quickstart
from dataclasses import dataclass
from apischema import serialize, deserialize
from apischema.validation.errors import ValidationError
@dataclass
class User:
id: int
name: str
email: str | None = None
# Serialization
user_obj = User(id=1, name="Alice", email="alice@example.com")
serialized_data = serialize(user_obj)
print(f"Serialized: {serialized_data}")
# Expected output: {'id': 1, 'name': 'Alice', 'email': 'alice@example.com'}
# Deserialization
deserialized_obj = deserialize(User, {'id': 2, 'name': 'Bob'})
print(f"Deserialized: {deserialized_obj}")
# Expected output: User(id=2, name='Bob', email=None)
# Handling validation errors
try:
deserialize(User, {'id': 'not-an-int', 'name': 'Charlie'})
except ValidationError as e:
print(f"Validation Error: {e}")
# Expected output: Validation Error: [id]: must be an integer