JSON Utilities API in Home Assistant Helpers: Complete Developer Guide

The JSON utilities API in Home Assistant helpers provides high-performance JSON serialization using orjson, custom encoders for Home Assistant objects, and robust error handling with diagnostic path mapping.

The home-assistant/core repository includes a comprehensive JSON utilities module located at homeassistant/helpers/json.py that standardizes how the platform serializes data to JSON. This API abstracts the complexity of encoding Home Assistant-specific objects while delivering superior performance through optimized libraries.

Core Components of the JSON Utilities API

High-Performance Encoding with orjson

The API leverages orjson for the majority of encoding operations because it is orders of magnitude faster than the standard library json module and natively supports dataclasses. The json_bytes function in homeassistant/helpers/json.py (lines 63-66) uses orjson.dumps with OPT_NON_STR_KEYS to handle non-string dictionary keys efficiently.

For deterministic output suitable for caching or hashing, json_dumps_sorted applies OPT_SORT_KEYS to guarantee consistent key ordering.

Custom JSON Encoders for Home Assistant Objects

The module provides multiple encoder strategies to handle Home Assistant's rich object ecosystem:

  • json_encoder_default (lines 38-55): A standalone default function used by orjson that handles json_fragment, collections, Path objects, datetime instances, and falls back to repr for unknown types.
  • JSONEncoder (lines 20-36): A subclass of json.JSONEncoder that recognizes objects exposing as_dict methods, plus native handling for datetime, set, and other common types.
  • ExtendedJSONEncoder (lines 70-88): Extends JSONEncoder to additionally serialize datetime.timedelta, date, time, and provides a safe repr-based dictionary for completely unknown types.

Error Handling and Serialization Diagnostics

When serialization fails, the API provides robust diagnostics through prepare_save_json (lines 63-78). This function captures TypeError exceptions from the encoder and invokes find_paths_unserializable_data (lines 18-68) to walk the data structure and locate the exact path of the offending element. It then raises a SerializationError (defined in homeassistant/util/json.py) with a human-readable path description.

Persistence and File Operations

The save_json function (lines 99-116) provides a high-level interface for writing JSON to disk. It handles mode selection (private files vs. world-readable), atomic writes via write_utf8_file_atomic, and integrates with the error handling pipeline. This ensures that configuration files and state storage are written safely without corruption risks.

Key Functions and Classes

The JSON utilities API exposes the following primary symbols:

  • json_bytes(data): Fast binary dump via orjson with OPT_NON_STR_KEYS.
  • json_dumps(data): Returns a UTF-8 string by decoding json_bytes.
  • json_dumps_sorted(data): Deterministic JSON string with sorted keys.
  • json_bytes_strip_null(data): Removes embedded NUL characters (\u0000) before dumping.
  • save_json(filename, data, private=False, encoder=None, atomic_writes=False): High-level file persistence with atomic write support.
  • prepare_save_json(data, encoder=None): Returns a (mode, json_payload) tuple with error detection.
  • find_paths_unserializable_data(bad_data, dump=json.dumps): Diagnostic walker to locate serialization failures.
  • json_encoder_default(obj): Default callback for orjson handling Home Assistant objects.
  • JSONEncoder: Standard library compatible encoder class.
  • ExtendedJSONEncoder: Extended encoder with additional type support and safe fallbacks.

Practical Code Examples

Serializing a Custom Home Assistant Object

from datetime import datetime
from homeassistant.helpers.json import json_dumps, JSONEncoder

class MyEntity:
    def __init__(self, name: str, when: datetime):
        self.name = name
        self.when = when

    def as_dict(self):
        # Home Assistant objects expose as_dict for JSONEncoder

        return {"name": self.name, "when": self.when}

entity = MyEntity("sensor.foo", datetime.utcnow())
payload = json_dumps(entity)          # uses JSONEncoder automatically

print(payload)                        # {"name":"sensor.foo","when":"2026-02-28T15:12:34.567890+00:00"}

Source: JSONEncoder implementation – homeassistant/helpers/json.py#L20-L36

Persisting a Configuration Dictionary Atomically

from homeassistant.helpers.json import save_json

config = {
    "scan_interval": 30,
    "devices": [{"id": "abc123", "enabled": True}]
}

# Write to a private file using an atomic rename to avoid corruption

save_json(
    filename="/config/.storage/my_integration.json",
    data=config,
    private=True,
    atomic_writes=True,
)

Source: save_json – homeassistant/helpers/json.py#L99-L116

Debugging a Serialization Error

from homeassistant.helpers.json import save_json, SerializationError
from homeassistant.helpers.json import find_paths_unserializable_data

bad_data = {"valid": 1, "bad": set([1, 2, 3])}  # orjson cannot handle set without default

try:
    save_json("bad.json", bad_data)
except SerializationError as err:
    # Locate the offending path

    paths = find_paths_unserializable_data(bad_data)
    print("Unserializable locations:", paths)

Source: prepare_save_json error handling – homeassistant/helpers/json.py#L63-L78

Removing Stray NUL Characters

from homeassistant.helpers.json import json_bytes_strip_null

data = {"name": "sensor\0foo", "value": 42}
binary = json_bytes_strip_null(data)   # NUL after "sensor" is stripped

print(binary.decode())                # {"name":"sensor","value":42}

Source: json_bytes_strip_null – homeassistant/helpers/json.py#L90-L112

Source File Reference

The JSON utilities API spans several key files in the home-assistant/core repository:

Summary

  • The JSON utilities API in Home Assistant helpers centralizes all JSON serialization logic in homeassistant/helpers/json.py.
  • It uses orjson for high-performance encoding via json_bytes and json_dumps, falling back to custom encoders for complex objects.
  • Custom encoders (JSONEncoder, ExtendedJSONEncoder, json_encoder_default) handle Home Assistant objects exposing as_dict, datetime objects, Path objects, and sets.
  • Robust error handling via prepare_save_json and find_paths_unserializable_data provides exact path diagnostics when serialization fails.
  • Safe persistence is handled by save_json, which supports atomic writes and private file permissions to prevent data corruption.

Frequently Asked Questions

What makes the Home Assistant JSON utilities faster than standard Python json?

The API uses orjson for the majority of operations, which is implemented in Rust and provides significantly better performance than Python's standard library json module. Functions like json_bytes leverage orjson.dumps with OPT_NON_STR_KEYS to handle non-string dictionary keys efficiently, while json_dumps_sorted uses OPT_SORT_KEYS for deterministic output without the performance penalty of Python's sort_keys parameter.

How does the API handle custom Home Assistant objects that aren't standard JSON types?

The API provides multiple encoder strategies through json_encoder_default, JSONEncoder, and ExtendedJSONEncoder. These recognize objects that expose an as_dict method (common in Home Assistant entities), as well as native Python types like datetime, set, Path, and timedelta. When an object cannot be natively encoded, the extended encoder falls back to a safe repr-based representation rather than raising an exception immediately.

What should I do when save_json throws a SerializationError?

When save_json raises a SerializationError, use the find_paths_unserializable_data function to diagnose the issue. This function walks your data structure and returns the exact path to the offending element that cannot be serialized. For example, if you accidentally included a set or a custom object without an as_dict method, the diagnostic output will pinpoint the exact location in your dictionary or list structure, allowing you to fix the data before retrying the save operation.

Where are the JSON utility functions located in the Home Assistant codebase?

The primary implementation resides in homeassistant/helpers/json.py, which contains the encoder classes, dump functions, and persistence helpers. Supporting infrastructure includes homeassistant/util/json.py (which defines SerializationError and formatting utilities) and homeassistant/util/file.py (which provides atomic file write operations used by save_json). These files work together to provide the complete JSON serialization stack used throughout the Home Assistant core.

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 →