How print_json() Handles JSON Serialization and Syntax Highlighting in Rich

Rich's print_json() function serializes Python objects or raw JSON strings into pretty-printed, syntax-highlighted terminal output by orchestrating the JSON renderable class and JSONHighlighter across three distinct architectural layers.

The print_json() function in Textualize/rich provides an elegant way to display JSON data with automatic formatting and syntax highlighting. Whether you pass a raw JSON string or a native Python dictionary, the library processes input through a pipeline spanning rich/console.py, rich/json.py, and rich/highlighter.py. Understanding this architecture reveals how Rich achieves its polished, colorized output.

The Entry Point: Console.print_json()

The API surface resides in rich/console.py at lines 1751-1797, where Console.print_json() serves as the primary interface. This method accepts two mutually exclusive inputs: a pre-formatted JSON string via the json parameter or a Python object via the data parameter.

When the json argument is None, the method delegates serialization to JSON.from_data() to encode the Python value. If a string is provided, the method validates the input type and constructs a JSON instance directly from the raw text. This branching logic ensures flexible input handling while maintaining strict type safety before rendering.

JSON Serialization in rich/json.py

The JSON class in rich/json.py manages encoding and pretty-printing logic. In JSON.__init__ (lines 25-51), the implementation parses the input string using json.loads(), then re-serializes it with the specified indent, ensure_ascii, and other formatting options to ensure consistent output.

For Python objects, JSON.from_data() at lines 54-99 performs the initial encoding using json.dumps(). This method accepts standard library parameters including default, skip_keys, allow_nan, and sort_keys, allowing fine-grained control over how complex Python objects convert to formatted JSON strings before highlighting is applied.

Syntax Highlighting with JSONHighlighter

Syntax highlighting is implemented by the JSONHighlighter class in rich/highlighter.py (lines 106-121). This highlighter extends RegexHighlighter to apply color spans matching JSON structures: braces, brackets, booleans, null, numbers, and strings.

After the base regex highlighting completes, JSONHighlighter.highlight() performs an additional semantic pass to detect object keys. It scans for string literals followed immediately by a colon outside of whitespace, applying the "json.key" style to distinguish dictionary keys from ordinary string values. When highlighting is disabled via highlight=False, the system instantiates NullHighlighter to bypass colorization while preserving formatting.

Rendering to the Terminal

Finally, Console.print_json() forwards the constructed JSON renderable to Console.print() with soft_wrap=True explicitly enabled. This parameter ensures long JSON lines wrap gracefully at word boundaries rather than character boundaries, preserving readability in narrow terminal windows without breaking the logical structure of the highlighted text.

Practical Code Examples

The following examples demonstrate the flexible input handling and customization options available through the print_json() API:

from rich import print_json

# Pretty-print a raw JSON string with default syntax highlighting

print_json('{"name": "Alice", "age": 30, "active": true}')

# Serialize a Python object with custom indentation

data = {"fruits": ["apple", "banana"], "count": 2, "available": None}
print_json(data=data, indent=4)

# Disable highlighting for plain-text output

print_json(data, highlight=False)

# Control Unicode escaping and NaN handling

print_json(
    {"value": "π", "nan": float("nan")},
    ensure_ascii=False,
    allow_nan=False
)

Summary

  • Input Routing: Console.print_json() in rich/console.py accepts either raw JSON strings (json=) or Python objects (data=), routing them through different initialization paths to ensure proper type handling.
  • Encoding Layer: The JSON class in rich/json.py handles all serialization via json.dumps() and json.loads(), supporting parameters like indent, ensure_ascii, allow_nan, and default callbacks for complex objects.
  • Colorization Engine: JSONHighlighter in rich/highlighter.py applies regex-based colorization and performs a secondary pass to identify object keys using the "json.key" style, distinguishing them from string values.
  • Terminal Output: The final renderable is printed with soft_wrap=True to ensure readable formatting regardless of terminal width, completing the pipeline from raw input to highlighted output.

Frequently Asked Questions

How does print_json() distinguish between JSON strings and Python objects?

print_json() checks the json parameter first. If None, it calls JSON.from_data() in rich/json.py to serialize the Python object provided via data. If a string is passed to json, the method validates the type and passes it directly to the JSON constructor. This mutually exclusive design prevents ambiguity between raw JSON text and Python dictionaries.

Can I customize the JSON serialization parameters when using print_json()?

Yes. When passing a Python object via the data parameter, JSON.from_data() forwards standard json.dumps() parameters including indent, default, sort_keys, ensure_ascii, and allow_nan. These control how Python objects are converted to formatted strings, allowing customization of indentation, Unicode escaping, and NaN handling.

Why are JSON object keys highlighted differently from string values?

The JSONHighlighter.highlight() method in rich/highlighter.py performs a secondary pass after initial regex highlighting. It scans for colons positioned immediately after string literals (outside whitespace) and applies the "json.key" style to those strings. This distinguishes dictionary keys from regular string values in the final colorized output.

Is it possible to disable syntax highlighting entirely?

Yes. Pass highlight=False to print_json(). This causes the JSON class to instantiate NullHighlighter instead of JSONHighlighter, resulting in plain text output without color spans while maintaining the pretty-printed formatting and indentation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →