mrkeyoor.com_
Sat 08 Aug 17:39 UTC
PyPIUtilsupdated 08 Aug 2026

ujson

ujson, or UltraJSON, is a Python JSON encoder and decoder implemented in C. Its loads, dumps, load, and dump functions resemble the standard json module, with extra output switches for HTML characters and forward slashes. It remains fast and widely installed, and current wheels cover many Python versions and platforms. The decisive fact is in the project's own README: its architecture is considered risky to change safely, the project is maintenance-only, and its maintainers tell users to migrate to orjson.

Verdict

Do not add ujson to a new project. Keep it only where measured performance and compatibility justify the migration delay, then plan the move its own maintainers recommend.

API stability5/5The small json-like API is mature and maintenance-only status makes feature-driven churn unlikely, though exact edge-case behavior still differs from the standard library.
Docs4/5The README gives an exceptionally clear project-status warning, option examples, benchmarks, threading limits, and build controls, while the formal API reference remains minimal.
Maintenance2/5The current 5.13.0 release and broad wheel matrix show caretaking, but maintainers accept only new-Python support plus critical bug and security fixes and reject normal feature work.
Ecosystem3/5Its json-like API and large installed base ease legacy use, but new performance-focused Python code has largely moved toward orjson and typed codecs such as msgspec.

Use it if

  • You maintain an existing application that already depends on ujson and changing JSON behavior now is riskier than keeping it pinned
  • You have benchmarks from your own payloads showing ujson materially helps a hot path and orjson's bytes output would force disruptive changes
  • You need a near-json-module string-returning API while completing a planned migration away from ujson
Skip it if

Setup reality

python -m pip install ujson usually selects one of the project's many prebuilt wheels and type stubs are included. Python 3.10 or newer is required. Less common interpreters, architectures, or distribution policies may force a C build; system double-conversion builds add ABI compatibility duties. Treat a move from json as a data-format change: test Unicode, NaN, custom types, byte input, ordering, and exact output before swapping imports.

Patterns

Encode a Python valueencode-json

import ujson

payload = {'ok': True, 'items': [1, 2, 3]}
text = ujson.dumps(payload)
print(text)

ujson.dumps returns str. This differs from orjson.dumps, which returns bytes.

Decode JSON text or bytesdecode-json

data = ujson.loads(b'{"name":"Ada","active":true}')
print(data['name'])

loads accepts str, bytes, or bytearray, but malformed input raises ujson.JSONDecodeError.

Handle malformed inputhandle-decode-error

try:
    data = ujson.loads(raw_body)
except ujson.JSONDecodeError as exc:
    raise ValueError('invalid JSON payload') from exc

Catch the specific decode exception when bad client input is expected; it is also a ValueError subclass.

Write JSON to a text filewrite-json-file

with open('report.json', 'w', encoding='utf-8') as fp:
    ujson.dump(report, fp, ensure_ascii=False, indent=2)

dump writes text, so open the file in text mode with an explicit encoding.

Read JSON from a fileread-json-file

with open('report.json', 'r', encoding='utf-8') as fp:
    report = ujson.load(fp)

load expects a file-like object with read(); passing a path string does not open the file.

Keep non-ASCII characters readableemit-utf8-text

text = ujson.dumps(
    {'city': 'Malmö'},
    ensure_ascii=False,
    escape_forward_slashes=False,
)

ensure_ascii defaults to true and forward slashes default to escaped, so set both when compact UTF-8 text matters.

Reject NaN and Infinityreject-nonstandard-numbers

text = ujson.dumps(measurements, allow_nan=False)

JSON does not define NaN or Infinity. The strict option prevents producing values that other parsers may reject.

Convert unsupported values explicitlyserialize-custom-type

from datetime import datetime

def json_default(value):
    if isinstance(value, datetime):
        return value.isoformat()
    raise TypeError(f'unsupported type: {type(value).__name__}')

text = ujson.dumps(event, default=json_default)

Let the default function raise for unknown types; silently stringifying everything can hide data-model mistakes.

Escape HTML-sensitive charactersescape-html-characters

text = ujson.dumps(
    {'fragment': '<script>alert(1)</script>'},
    encode_html_chars=True,
)

This escapes angle brackets and ampersands, but JSON encoding alone is not a complete defense for every HTML or script context.

Sort keys and control separatorsproduce-stable-output

text = ujson.dumps(
    record,
    sort_keys=True,
    separators=(',', ': '),
    ensure_ascii=False,
)

Sorted keys help snapshots and diffs, but do not turn JSON into a cryptographic canonicalization format.

Alternatives

PackageRegistryPick it when
orjsonPyPIYou want the replacement recommended by ujson's maintainers and can accept dumps returning bytes
msgspecPyPIYou want fast JSON plus typed schema validation and structured decoding
python-rapidjsonPyPIYou need RapidJSON-specific parse, number, datetime, or UUID controls