# JSON Utilities API in Home Assistant Helpers: Complete Developer Guide

> Explore the Home Assistant JSON utilities API for high-performance serialization with orjson custom encoders and error handling. Master JSON in HA helpers.

- Repository: [Home Assistant/core](https://github.com/home-assistant/core)
- Tags: developer-guide
- Published: 2026-02-28

---

**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`](https://github.com/home-assistant/core/blob/main/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`](https://github.com/home-assistant/core/blob/main/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`](https://github.com/home-assistant/core/blob/main/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

```python
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`](https://github.com/home-assistant/core/blob/dev/homeassistant/helpers/json.py#L20-L36)

### Persisting a Configuration Dictionary Atomically

```python
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`](https://github.com/home-assistant/core/blob/dev/homeassistant/helpers/json.py#L99-L116)

### Debugging a Serialization Error

```python
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`](https://github.com/home-assistant/core/blob/dev/homeassistant/helpers/json.py#L63-L78)

### Removing Stray NUL Characters

```python
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`](https://github.com/home-assistant/core/blob/dev/homeassistant/helpers/json.py#L90-L112)

## Source File Reference

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

- **[`homeassistant/helpers/json.py`](https://github.com/home-assistant/core/blob/main/homeassistant/helpers/json.py)**: Central implementation containing `JSONEncoder`, `json_bytes`, `save_json`, and diagnostic functions.
- **[`homeassistant/util/json.py`](https://github.com/home-assistant/core/blob/main/homeassistant/util/json.py)**: Defines `SerializationError` and `format_unserializable_data` used by the helpers for error reporting.
- **[`homeassistant/util/file.py`](https://github.com/home-assistant/core/blob/main/homeassistant/util/file.py)**: Provides `write_utf8_file` and `write_utf8_file_atomic` used by `save_json` for safe disk writes.

## Summary

- The **JSON utilities API in Home Assistant helpers** centralizes all JSON serialization logic in [`homeassistant/helpers/json.py`](https://github.com/home-assistant/core/blob/main/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`](https://github.com/home-assistant/core/blob/main/homeassistant/helpers/json.py), which contains the encoder classes, dump functions, and persistence helpers. Supporting infrastructure includes [`homeassistant/util/json.py`](https://github.com/home-assistant/core/blob/main/homeassistant/util/json.py) (which defines `SerializationError` and formatting utilities) and [`homeassistant/util/file.py`](https://github.com/home-assistant/core/blob/main/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.