dr-serialize
| Repo Definitions | Terms TOML | Contracts TOML |
|---|
dr-serialize normalizes Python values into JSON-encodable data and produces deterministic JSON text, bytes, hashes, and identities. Its functionality is organized into four areas supported by shared infrastructure:
- Normalization converts Python values into bounded, JSON-shaped data through extensible conversion rules for diagnostics and storage. Non-finite floats may survive normalization outside canonical set ordering.
- Canonical JSON renders bounded finite strict JSON values as deterministic text and exact UTF-8 bytes, projects unordered collections into stable arrays, and produces validated SHA-256 digests.
- Strict decoding parses one complete UTF-8 JSON value under explicit byte and depth limits while rejecting duplicate keys, non-finite numbers, and malformed or trailing input.
- Identity validates a fixed document shape around a domain-owned payload and derives stable canonical bytes and a full identity hash without normalization.
- Infra
provides the contracts shared by those areas:
- recursive JSON values and iterative strict validation;
- validated full SHA-256 digests;
- diagnostic paths, typed errors, and bounded metadata;
- a common UTF-8 encoding invariant.
The declarations below are abbreviated contract shapes; ... replaces
implementation details.
Normalization
Normalization is policy-driven and may be lossy. A Serializer combines
explicit depth and size limits with an ordered chain of consumer handlers, and
produces JSON-encodable, Jsonable-shaped data for diagnostics or storage
rather than identity. Non-finite floats may survive normal conversion outside
canonical set ordering.
class SerializationLimits(BaseModel):
max_depth: int = 200
max_bytes: int
hard_max_bytes: int | None = None
def postgres_jsonb_limits(
max_bytes: int = POSTGRES_JSONB_PAYLOAD_MAX_BYTES,
) -> SerializationLimits: ...
type JsonableHandle = tuple[bool, Any]
type JsonableHandler = Callable[
[Any, ConversionContext],
JsonableHandle,
]
@dataclass(frozen=True, slots=True)
class ConversionContext:
serializer: Serializer
depth: int
path: JsonPath
def convert(
self,
child: Any,
key: str | int | None = None,
) -> Jsonable: ...
@dataclass(frozen=True, slots=True)
class Serializer:
limits: SerializationLimits
handlers: tuple[JsonableHandler, ...] = ()
def to_jsonable(self, x: Any) -> Jsonable: ...
Canonical JSON
Canonical JSON consumes finite strict JSON values without applying handlers or selecting domain fields. Profile v1 admits at most 200 nested containers and 640 decimal digits per integer; scalars have depth 0 and a root list or object has depth 1. It then uses the standard-library JSON encoder; canonical text is the stable contract from which exact bytes and hashes are derived.
CANONICAL_JSON_MAX_CONTAINER_DEPTH: Final[int] = 200
CANONICAL_JSON_MAX_INTEGER_DIGITS: Final[int] = 640
def canonical_json(value: Jsonable) -> str: ...
def canonical_json_bytes(value: Jsonable, /) -> bytes: ...
def json_hash(
value: Jsonable,
*,
length: int | None = None,
) -> Sha256Digest | str: ...
def canonical_sorted_values(
values: Iterable[Jsonable],
/,
) -> list[Jsonable]: ...
canonical_sorted_values projects only logically unordered collections into a
stable array. It does not reorder arrays whose existing order is meaningful.
Strict decoding
Strict decoding accepts exactly one bounded UTF-8 JSON value without coercion. Failure messages, structured diagnostics, and exception cause and context do not echo or retain input. Traceback locals are outside this guarantee.
def decode_strict_json_bytes(
data: bytes,
/,
*,
max_bytes: int,
max_depth: int,
) -> Jsonable: ...
class StrictJsonDecodeError(SerializationError): ...
class JsonByteLimitError(StrictJsonDecodeError): ...
class JsonDepthLimitError(StrictJsonDecodeError): ...
class InvalidUtf8Error(StrictJsonDecodeError): ...
class JsonSyntaxError(StrictJsonDecodeError): ...
class DuplicateJsonKeyError(StrictJsonDecodeError): ...
class NonFiniteJsonNumberError(StrictJsonDecodeError): ...
Identity
The owning domain supplies every identity-bearing fact. dr-serialize validates
the fixed document envelope against the same complete Canonical JSON Text
profile, applies copy.deepcopy during construction and payload access, and
derives canonical identity bytes and a full hash without normalization.
Accepted custom container subclasses control whether the deep-copy protocol
yields alias isolation.
class IdentityDocument:
schema: str
schema_version: int
def __init__(
self,
schema: str,
schema_version: int,
payload: Jsonable,
) -> None: ...
@property
def payload(self) -> Jsonable: ...
def to_json_dict(self) -> dict[str, Jsonable]: ...
def build_identity_document(
*,
schema: str,
schema_version: int,
payload: Any,
) -> IdentityDocument: ...
def validate_identity_document(
document: dict[Any, Any],
) -> IdentityDocument: ...
def canonical_identity_json_bytes(
document: IdentityDocument,
/,
) -> bytes: ...
def identity_document_hash(
document: IdentityDocument,
) -> Sha256Digest: ...
Shared infrastructure
The shared infrastructure defines the recursive value, digest, and diagnostic
contracts used across the four functional areas. Finite-number validation is a
runtime property of strict Jsonable values because Python's type system cannot
express it in the recursive alias.
type Jsonable = (
None
| bool
| int
| float
| str
| list[Jsonable]
| dict[str, Jsonable]
)
def validate_strict_json(value: Any) -> Jsonable: ...
class Sha256Digest(str):
@classmethod
def parse(cls, value: str, /) -> Self: ...
type JsonPath = tuple[str | int, ...]
class SerializationError(Exception):
path: JsonPath
detail: str
def diagnostics(self) -> dict[str, Any]: ...
Development
Install dependencies and the commit hook once per clone:
uv sync --locked
uv run pre-commit install
The hook runs scripts/pre-check.sh for Ruff formatting, Ruff lint, and type
checking, followed by the test suite.
Metadata
Release files for dr-serialize 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dr_serialize-0.1.2.tar.gz | 17.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dr_serialize-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.4 kB
Release files / dr_serialize-0.1.2.tar.gz
| Download URL | dr_serialize-0.1.2.tar.gz |
|---|---|
| Size | 17.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
02662cbb9ad3f1262a81bc14a2f3254f925f880333da69eac6dbda2226d1c51f
|
|
BLAKE2b-256 checksum How to use checksums |
5e2a25dd5859ddfd78ee604a59c6ab81a0601669506a6af6ea871fc4438955bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / dr_serialize-0.1.2-py3-none-any.whl
| Download URL | dr_serialize-0.1.2-py3-none-any.whl |
|---|---|
| Size | 27.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
785015ceb779906bd03965fd541d1733772b45fefbd2d5473304b7f5db60ce5d
|
|
BLAKE2b-256 checksum How to use checksums |
ccb7511d474c07440ff8de4c78aa637a461746c5a5dca9e539fca06b2d015722
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency log