jsonpickle

Serializes and deserializes arbitrary Python object graphs to and from JSON, including custom classes.

Library
PyPI
v4.1.2
1,318stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
80/100Excellent
Development Activity84
Maintenance64
Community84
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture82
Code Quality88
Innovation68
Learning Curve85

jsonpickle converts arbitrary Python objects into JSON and back again, going beyond what the standard library’s json module supports. Where json.dumps chokes on custom classes, datetimes, sets, and other non-primitive types, jsonpickle walks the object graph, records type information and object references as it goes, and can reconstruct the original object on decode rather than just a plain-dict approximation of it.

It builds on whichever JSON backend is available (simplejson, the standard json module, or ujson) and adds a handler registry so libraries and applications can teach it how to (de)serialize their own types. Bundled extensions cover common numeric/scientific cases: numpy arrays, pandas DataFrames, and scikit-learn objects can all be encoded when the corresponding optional dependency is installed.

What You Get

  • Two-way encode/decode of arbitrary object graphs, not just dicts, lists, and primitives
  • Object reference and cycle detection so shared or circular references survive a round trip via py/id and py/ref tags
  • A handler registry (jsonpickle.handlers.register) for teaching jsonpickle custom flatten/restore logic per type
  • Pluggable JSON backend support (json, simplejson, ujson) with configurable fallthrough between them
  • Built-in extensions for numpy arrays, pandas DataFrames, and scikit-learn objects
  • Fine-grained encode options: max_depth, max_iter, unpicklable=False for lossy-but-readable output, and use_base85 for compact binary data

Common Use Cases

  • Persisting arbitrary Python objects, including custom classes, to disk or a database as JSON instead of binary pickle
  • Storing serialized data somewhere that needs to be human-readable or indexable, e.g. an S3 bucket queried via Athena
  • Serializing scikit-learn models, numpy arrays, or pandas DataFrames into JSON for interchange with non-numpy/pandas-aware consumers
  • Snapshotting complex application state, including cyclic references, for caching or test fixtures
  • Passing rich Python objects between processes or services when the transport layer expects JSON

Under The Hood

Architecture The library is organized around a small set of cooperating modules rather than one big class: pickler.py defines the Pickler class and top-level encode(), which walks an object graph and flattens it into JSON-safe structures tagged with reserved keys from tags.py (py/object, py/id, py/ref, py/reduce, etc.); unpickler.py mirrors this with Unpickler/decode(), which reads those tags back and reconstructs the original types, including resolving py/id references to reproduce shared/cyclic object identity. handlers.py implements a Registry that custom and built-in handlers register against, consulted by both the pickler and unpickler when a type has bespoke (de)serialization needs; backend.py’s JSONBackend abstracts over the underlying JSON encoder/decoder (trying simplejson, json, ujson in order with fallthrough), and util.py centralizes the type-introspection helpers (_is_type, PRIMITIVES, SEQUENCES, etc.) both core modules depend on. The ext/ package (numpy.py, pandas.py, gmpy.py, yaml.py) plugs into this same handler registry rather than being special-cased in the core, so optional scientific-stack support is additive and only activates when explicitly registered.

Tech Stack jsonpickle has zero runtime dependencies beyond the Python standard library (pyproject.toml declares dependencies = []), targeting Python 3.10-3.14. It automatically picks up simplejson or ujson if installed for faster/alternate JSON handling, and its optional testing extra pulls in numpy, pandas, scikit-learn, SQLAlchemy, PyMongo, ecdsa, gmpy2, and PyYAML purely to exercise the corresponding extension handlers. The build uses setuptools with setuptools_scm for version derivation from git tags, and packaging/release automation (twine, pypi-attestations) runs via GitHub Actions on tagged pushes.

Code Quality The test suite (tests/) is extensive — over 6,000 lines across dedicated files per concern (jsonpickle_test.py, collections_test.py, datetime_test.py, numpy_test.py, pandas_test.py, sklearn_test.py, sqlalchemy_test.py, stdlib_test.py, plus a helper.py for shared fixtures), run with pytest and gated in CI via pytest-ruff and pytest-checkdocs. mypy.ini enables strict = True project-wide, and the public API in pickler.py/unpickler.py/handlers.py is fully type-annotated with modern syntax (X | None, TypeAlias). Formatting and linting run through ruff (replacing black) plus isort, enforced in a dedicated lint.yml GitHub Actions workflow separate from the test workflow, and there’s a fuzzing harness (fuzzing/, atheris) exercising the decoder against malformed input.

API Design The public surface is deliberately small and mirrors the stdlib json module’s shape: top-level encode/decode (aliased as dumps/loads for drop-in familiarity), with extensive keyword-only options (unpicklable, max_depth, use_base85, handler_context, etc.) documented inline via detailed docstrings rather than requiring separate reading. Custom-type support is opt-in and decorator-friendly (@jsonpickle.handlers.register(Foo, base=True)), and optional numpy/pandas/gmpy/yaml support is enabled explicitly by importing and calling register_handlers() on the relevant jsonpickle.ext submodule, keeping the core import lightweight for users who don’t need those extensions.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search