typed-json
stdlib json.loads/dumps, typed as a recursive JsonValue instead of Any.
json.loads is annotated -> Any, which silently switches off type checking
for everything you do with the result. typed-json narrows that boundary to
JsonValue — a recursive union
(None | bool | int | float | str | list | dict) that the type checker can
actually follow — so a single un-typed value can't quietly poison the types
downstream of it.
from typed_json import loads, dumps
value = loads('{"items": [1, 2.5, null]}') # JsonValue, not Any
text = dumps(value) # input constrained to JsonValue
The contract: no Any
That's the whole promise — nothing more, nothing less.
loads/loadcast the stdlib result toJsonValue. Under the default decoder (no customparse_*/object_hooksettings)json.loadsprovably returns a value withinJsonValue, so the cast is sound at zero runtime cost — no validation pass.dumps/dumpaccept onlyJsonValue. Because that type is exactly the set of natively-serializable values, the checker rejects aset/datetimestatically, and nodefault=hook is ever needed.
When stdlib's guarantee doesn't apply: the guards
For a value of genuinely unknown origin — an object/Any from another
library, a YAML/msgpack/pickle load, hand-built data — cast is not sound.
Reach for the TypeGuards, which validate at runtime by recursing the tree:
from typed_json import is_json_value
def handle(payload: object) -> None:
if is_json_value(payload):
reveal_type(payload) # JsonValue
Also available: is_json_primitive, is_json_array, is_json_object.
Types
JsonValue, JsonPrimitive, JsonObject (dict[str, JsonValue]), and
JsonArray (list[JsonValue]) are exported as PEP 695 type aliases.
Install
uv add python-typed-json # or: pip install python-typed-json
The PyPI name carries a python- prefix because an unrelated, dormant
typedjson project blocks the bare name; the module you import is plain
typed_json, in the tradition of python-dateutil and python-dotenv.
Requires Python ≥ 3.12 (PEP 695 type statements). Zero runtime dependencies.
License
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_typed_json-0.1.0.tar.gz.
File metadata
- Download URL: python_typed_json-0.1.0.tar.gz
- Upload date:
- Size: 12.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4c6a683ed8773113d91c33551788700b2785500799daeaad0b60d6d027892c6
|
|
| MD5 |
be22e4df879a4bdb51351c2a710d8f6e
|
|
| BLAKE2b-256 |
9839414bd3f01aa454ec1a580b5fb9bfd7ef4a32e84b45674fb7c0d43ef4ec28
|
File details
Details for the file python_typed_json-0.1.0-py3-none-any.whl.
File metadata
- Download URL: python_typed_json-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cdae9a75b68a53ff64cacc219f11717ffc3f2b9dcec04f125606c0ab0265962c
|
|
| MD5 |
e10844f7b037978f00917107dd854282
|
|
| BLAKE2b-256 |
c1f887a969c50b7e1352d725771919ac9733581a9e6d17334f86e11f394a593b
|