Skip to main content

Explain exactly why and where Python objects fail JSON serialization

Project description

jsonwhy

Python's JSON encoder tells you which type failed, but not where that value is inside a large payload. jsonwhy adds the missing path and reports other problems it finds in the same pass.

from datetime import datetime

import jsonwhy

payload = {
    "users": [{"name": "Ada", "joined": datetime(2026, 7, 12)}],
    "tags": {"python", "json"},
}

jsonwhy.dumps(payload)
jsonwhy.JsonWhyError: JSON serialization failed with 2 issues:
1. $.users[0].joined: Object of type datetime is not JSON serializable.
   Fix: Convert it with value.isoformat(); preserve timezone information.
2. $.tags: Object of type set is not JSON serializable.
   Fix: Convert it to a list; sort first if deterministic output matters.

Install

python -m pip install jsonwhy

Python 3.10 or newer is required. The package has no runtime dependencies.

API

dumps() and dump() accept the standard json options. Valid input is passed through to the standard library; diagnosis only runs after serialization fails.

encoded = jsonwhy.dumps({"ok": True}, indent=2)

with open("data.json", "w", encoding="utf-8") as output:
    jsonwhy.dump({"ok": True}, output)

Use explain() when you want structured results without raising an exception:

issues = jsonwhy.explain(payload)

for issue in issues:
    print(issue.path)
    print(issue.kind)
    print(issue.suggestion)
    print(issue.as_dict())

Two shorter checks are also available:

jsonwhy.check(payload)                 # bool
jsonwhy.assert_serializable(payload)   # raises JsonWhyError

jsonwhy detects unsupported values and keys, circular references, non-finite floats when allow_nan=False, failures in custom default handlers, and overly deep structures.

Custom suggestions

Applications can register advice for their own types:

class CustomerId:
    pass


jsonwhy.register_suggestion(CustomerId, "Convert it with str(value).")

This changes the suggested fix only. jsonwhy does not silently convert the value.

Command line

The CLI checks Python literals, which is useful for values such as sets, bytes, complex numbers, and tuple keys.

jsonwhy "{'payload': b'hello', 'tags': {'a', 'b'}}"
jsonwhy --json "{'payload': b'hello'}"

Exit status 0 means compatible, 1 means issues were found, and 2 means the input or command was invalid.

Notes

  • A failing dump() may have written part of its output before the error.
  • Diagnosis may call a custom default handler or construct a custom encoder again after the original failure. These hooks should be safe to repeat.
  • Diagnostic text can contain representations of application values. Treat it with the same care as logs and tracebacks.
  • Custom repr() implementations can perform work or have side effects before their resulting text is shortened.

Bug reports are welcome on the GitHub issue tracker.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jsonwhy-0.1.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jsonwhy-0.1.0-py3-none-any.whl (12.4 kB view details)

Uploaded Python 3

File details

Details for the file jsonwhy-0.1.0.tar.gz.

File metadata

  • Download URL: jsonwhy-0.1.0.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for jsonwhy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bebee1800bd316272621c2245a349ffd4c8ecc4b81c7230abaae13e4be59bf1d
MD5 6d61f3dec7fef840660680f0fe1b37de
BLAKE2b-256 854add2bcc9e1a62b174e9ddde6f1a0d77352ef2f00253db5a1d09cbc094ce98

See more details on using hashes here.

Provenance

The following attestation bundles were made for jsonwhy-0.1.0.tar.gz:

Publisher: publish.yml on Abhay-2004/jsonwhy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file jsonwhy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: jsonwhy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for jsonwhy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a880fa22022e51f1f1ed42ace95c1294b65e632719facb339afdbec602a71693
MD5 37e701a9e0803d310978205fedcf791c
BLAKE2b-256 0ffd7b9e2705df061e6113fd65270ff4c2543073dd9b3dba652bc184e6878152

See more details on using hashes here.

Provenance

The following attestation bundles were made for jsonwhy-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Abhay-2004/jsonwhy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page