Skip to content

jsonx API Reference

Auto-generated API documentation for the jsonx (extended JSON) parser module.

jsonx

Extended JSON parser — zero dependencies, stdlib only, Python 3.10+.

Part of zerodep: https://github.com/Oaklight/zerodep Copyright (c) 2026 Peng Ding. MIT License.

Drop-in replacement for commentjson / stdlib json with JSONC support, plus JSONL (JSON Lines) helpers.

Supports
  • Single-line comments: // and #
  • Block comments: /* ... */
  • Trailing commas in objects and arrays
  • All standard JSON types
  • JSONL (one JSON value per line, with optional comments)

Example::

loads('{"a": 1, // comment

"b": 2}') # {'a': 1, 'b': 2} load(open("config.jsonc")) # {...}

# JSONL with comments
loads_lines('{"a":1}

// skip {"b":2}') # [{'a': 1}, {'b': 2}]

JSONCDecodeError

Bases: JSONDecodeError

Error raised when JSONC parsing fails.

Provides line and column numbers relative to the original JSONC source (before comment/trailing-comma stripping).

Source code in jsonx/jsonx.py
class JSONCDecodeError(json.JSONDecodeError):
    """Error raised when JSONC parsing fails.

    Provides line and column numbers relative to the original JSONC source
    (before comment/trailing-comma stripping).
    """

loads(text, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kwargs)

Deserialize a JSONC string to a Python object.

Strips //, #, and /* */ comments and trailing commas before delegating to :func:json.loads.

Parameters:

Name Type Description Default
text str

JSONC source string.

required
cls type[JSONDecoder] | None

Custom JSON decoder class.

None
object_hook Any

Called with the result of any object literal decoded.

None
parse_float Any

Called with every JSON float string decoded.

None
parse_int Any

Called with every JSON int string decoded.

None
parse_constant Any

Called with -Infinity, Infinity, NaN.

None
object_pairs_hook Any

Called with an ordered list of pairs.

None
**kwargs Any

Additional keyword arguments passed to :func:json.loads.

{}

Returns:

Type Description
Any

Deserialized Python object.

Raises:

Type Description
JSONCDecodeError

If the text is not valid JSONC.

Source code in jsonx/jsonx.py
def loads(
    text: str,
    *,
    cls: type[json.JSONDecoder] | None = None,
    object_hook: Any = None,
    parse_float: Any = None,
    parse_int: Any = None,
    parse_constant: Any = None,
    object_pairs_hook: Any = None,
    **kwargs: Any,
) -> Any:
    """Deserialize a JSONC string to a Python object.

    Strips ``//``, ``#``, and ``/* */`` comments and trailing commas before
    delegating to :func:`json.loads`.

    Args:
        text: JSONC source string.
        cls: Custom JSON decoder class.
        object_hook: Called with the result of any object literal decoded.
        parse_float: Called with every JSON float string decoded.
        parse_int: Called with every JSON int string decoded.
        parse_constant: Called with ``-Infinity``, ``Infinity``, ``NaN``.
        object_pairs_hook: Called with an ordered list of pairs.
        **kwargs: Additional keyword arguments passed to :func:`json.loads`.

    Returns:
        Deserialized Python object.

    Raises:
        JSONCDecodeError: If the text is not valid JSONC.
    """
    cleaned = _preprocess(text)
    try:
        return json.loads(
            cleaned,
            cls=cls,
            object_hook=object_hook,
            parse_float=parse_float,
            parse_int=parse_int,
            parse_constant=parse_constant,
            object_pairs_hook=object_pairs_hook,
            **kwargs,
        )
    except json.JSONDecodeError as exc:
        line, col = _remap_error_position(text, cleaned, exc.pos)
        raise JSONCDecodeError(exc.msg, text, exc.pos) from None

load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kwargs)

Deserialize a JSONC file to a Python object.

Parameters:

Name Type Description Default
fp IO[str]

A text file-like object containing JSONC.

required
cls type[JSONDecoder] | None

Custom JSON decoder class.

None
object_hook Any

Called with the result of any object literal decoded.

None
parse_float Any

Called with every JSON float string decoded.

None
parse_int Any

Called with every JSON int string decoded.

None
parse_constant Any

Called with -Infinity, Infinity, NaN.

None
object_pairs_hook Any

Called with an ordered list of pairs.

None
**kwargs Any

Additional keyword arguments passed to :func:json.loads.

{}

Returns:

Type Description
Any

Deserialized Python object.

Raises:

Type Description
JSONCDecodeError

If the content is not valid JSONC.

Source code in jsonx/jsonx.py
def load(
    fp: IO[str],
    *,
    cls: type[json.JSONDecoder] | None = None,
    object_hook: Any = None,
    parse_float: Any = None,
    parse_int: Any = None,
    parse_constant: Any = None,
    object_pairs_hook: Any = None,
    **kwargs: Any,
) -> Any:
    """Deserialize a JSONC file to a Python object.

    Args:
        fp: A text file-like object containing JSONC.
        cls: Custom JSON decoder class.
        object_hook: Called with the result of any object literal decoded.
        parse_float: Called with every JSON float string decoded.
        parse_int: Called with every JSON int string decoded.
        parse_constant: Called with ``-Infinity``, ``Infinity``, ``NaN``.
        object_pairs_hook: Called with an ordered list of pairs.
        **kwargs: Additional keyword arguments passed to :func:`json.loads`.

    Returns:
        Deserialized Python object.

    Raises:
        JSONCDecodeError: If the content is not valid JSONC.
    """
    return loads(
        fp.read(),
        cls=cls,
        object_hook=object_hook,
        parse_float=parse_float,
        parse_int=parse_int,
        parse_constant=parse_constant,
        object_pairs_hook=object_pairs_hook,
        **kwargs,
    )

dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kwargs)

Serialize a Python object to a JSON string.

This is a pass-through to :func:json.dumps for API compatibility.

Parameters:

Name Type Description Default
obj Any

Python object to serialize.

required
skipkeys bool

Skip keys that are not basic types.

False
ensure_ascii bool

Escape non-ASCII characters.

True
check_circular bool

Check for circular references.

True
allow_nan bool

Allow NaN, Infinity, -Infinity.

True
cls type[JSONEncoder] | None

Custom JSON encoder class.

None
indent int | str | None

Indentation level for pretty-printing.

None
separators tuple[str, str] | None

Item and key separators.

None
default Any

Called for objects that are not serializable.

None
sort_keys bool

Sort dictionary keys.

False
**kwargs Any

Additional keyword arguments passed to :func:json.dumps.

{}

Returns:

Type Description
str

JSON string.

Source code in jsonx/jsonx.py
def dumps(
    obj: Any,
    *,
    skipkeys: bool = False,
    ensure_ascii: bool = True,
    check_circular: bool = True,
    allow_nan: bool = True,
    cls: type[json.JSONEncoder] | None = None,
    indent: int | str | None = None,
    separators: tuple[str, str] | None = None,
    default: Any = None,
    sort_keys: bool = False,
    **kwargs: Any,
) -> str:
    """Serialize a Python object to a JSON string.

    This is a pass-through to :func:`json.dumps` for API compatibility.

    Args:
        obj: Python object to serialize.
        skipkeys: Skip keys that are not basic types.
        ensure_ascii: Escape non-ASCII characters.
        check_circular: Check for circular references.
        allow_nan: Allow ``NaN``, ``Infinity``, ``-Infinity``.
        cls: Custom JSON encoder class.
        indent: Indentation level for pretty-printing.
        separators: Item and key separators.
        default: Called for objects that are not serializable.
        sort_keys: Sort dictionary keys.
        **kwargs: Additional keyword arguments passed to :func:`json.dumps`.

    Returns:
        JSON string.
    """
    return json.dumps(
        obj,
        skipkeys=skipkeys,
        ensure_ascii=ensure_ascii,
        check_circular=check_circular,
        allow_nan=allow_nan,
        cls=cls,
        indent=indent,
        separators=separators,
        default=default,
        sort_keys=sort_keys,
        **kwargs,
    )

dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kwargs)

Serialize a Python object to a JSON file.

This is a pass-through to :func:json.dump for API compatibility.

Parameters:

Name Type Description Default
obj Any

Python object to serialize.

required
fp IO[str]

A text file-like object to write to.

required
skipkeys bool

Skip keys that are not basic types.

False
ensure_ascii bool

Escape non-ASCII characters.

True
check_circular bool

Check for circular references.

True
allow_nan bool

Allow NaN, Infinity, -Infinity.

True
cls type[JSONEncoder] | None

Custom JSON encoder class.

None
indent int | str | None

Indentation level for pretty-printing.

None
separators tuple[str, str] | None

Item and key separators.

None
default Any

Called for objects that are not serializable.

None
sort_keys bool

Sort dictionary keys.

False
**kwargs Any

Additional keyword arguments passed to :func:json.dump.

{}
Source code in jsonx/jsonx.py
def dump(
    obj: Any,
    fp: IO[str],
    *,
    skipkeys: bool = False,
    ensure_ascii: bool = True,
    check_circular: bool = True,
    allow_nan: bool = True,
    cls: type[json.JSONEncoder] | None = None,
    indent: int | str | None = None,
    separators: tuple[str, str] | None = None,
    default: Any = None,
    sort_keys: bool = False,
    **kwargs: Any,
) -> None:
    """Serialize a Python object to a JSON file.

    This is a pass-through to :func:`json.dump` for API compatibility.

    Args:
        obj: Python object to serialize.
        fp: A text file-like object to write to.
        skipkeys: Skip keys that are not basic types.
        ensure_ascii: Escape non-ASCII characters.
        check_circular: Check for circular references.
        allow_nan: Allow ``NaN``, ``Infinity``, ``-Infinity``.
        cls: Custom JSON encoder class.
        indent: Indentation level for pretty-printing.
        separators: Item and key separators.
        default: Called for objects that are not serializable.
        sort_keys: Sort dictionary keys.
        **kwargs: Additional keyword arguments passed to :func:`json.dump`.
    """
    json.dump(
        obj,
        fp,
        skipkeys=skipkeys,
        ensure_ascii=ensure_ascii,
        check_circular=check_circular,
        allow_nan=allow_nan,
        cls=cls,
        indent=indent,
        separators=separators,
        default=default,
        sort_keys=sort_keys,
        **kwargs,
    )

loads_lines(text, **kwargs)

Deserialize a JSONL string to a list of Python objects.

Uses a batch fast-path for clean JSONL: non-empty lines are joined into a JSON array and parsed in a single :func:json.loads call, matching ndjson-level performance. If that fails (comments, trailing commas, etc.), falls back to per-line JSONC processing.

Parameters:

Name Type Description Default
text str

JSONL source string (one JSON value per line).

required
**kwargs Any

Keyword arguments forwarded to :func:json.loads (or :func:loads on fallback).

{}

Returns:

Type Description
list[Any]

List of deserialized Python objects.

Raises:

Type Description
JSONCDecodeError

If any line contains invalid JSON/JSONC.

Source code in jsonx/jsonx.py
def loads_lines(
    text: str,
    **kwargs: Any,
) -> list[Any]:
    """Deserialize a JSONL string to a list of Python objects.

    Uses a batch fast-path for clean JSONL: non-empty lines are joined
    into a JSON array and parsed in a single :func:`json.loads` call,
    matching ``ndjson``-level performance.  If that fails (comments,
    trailing commas, etc.), falls back to per-line JSONC processing.

    Args:
        text: JSONL source string (one JSON value per line).
        **kwargs: Keyword arguments forwarded to :func:`json.loads`
            (or :func:`loads` on fallback).

    Returns:
        List of deserialized Python objects.

    Raises:
        JSONCDecodeError: If any line contains invalid JSON/JSONC.
    """
    lines = text.split("\n")
    stripped = [ln for ln in lines if ln.strip()]
    if not stripped:
        return []
    # Fast path: join non-empty lines into a JSON array, single parse.
    # This avoids per-line Python overhead and lets the C json parser
    # handle everything in one call.
    _json_loads = json.loads
    try:
        return _json_loads("[" + ",".join(stripped) + "]", **kwargs)
    except json.JSONDecodeError:
        pass
    # Slow path: comments, trailing commas, or JSONC syntax present.
    results: list[Any] = []
    for line in lines:
        if _is_blank_or_comment(line):
            continue
        try:
            results.append(_json_loads(line, **kwargs))
        except json.JSONDecodeError:
            results.append(loads(line, **kwargs))
    return results

load_lines(fp, **kwargs)

Deserialize a JSONL file to a list of Python objects.

Parameters:

Name Type Description Default
fp IO[str]

A text file-like object containing JSONL.

required
**kwargs Any

Keyword arguments forwarded to :func:loads.

{}

Returns:

Type Description
list[Any]

List of deserialized Python objects.

Raises:

Type Description
JSONCDecodeError

If any line contains invalid JSON/JSONC.

Source code in jsonx/jsonx.py
def load_lines(
    fp: IO[str],
    **kwargs: Any,
) -> list[Any]:
    """Deserialize a JSONL file to a list of Python objects.

    Args:
        fp: A text file-like object containing JSONL.
        **kwargs: Keyword arguments forwarded to :func:`loads`.

    Returns:
        List of deserialized Python objects.

    Raises:
        JSONCDecodeError: If any line contains invalid JSON/JSONC.
    """
    return loads_lines(fp.read(), **kwargs)

dumps_lines(objects, **kwargs)

Serialize a list of Python objects to a JSONL string.

Each object is serialized on its own line using :func:json.dumps. No trailing newline is emitted (consistent with "\n".join(...) semantics).

Parameters:

Name Type Description Default
objects list[Any]

Iterable of Python objects to serialize.

required
**kwargs Any

Keyword arguments forwarded to :func:json.dumps.

{}

Returns:

Type Description
str

JSONL string (one JSON value per line).

Source code in jsonx/jsonx.py
def dumps_lines(
    objects: list[Any],
    **kwargs: Any,
) -> str:
    """Serialize a list of Python objects to a JSONL string.

    Each object is serialized on its own line using :func:`json.dumps`.
    No trailing newline is emitted (consistent with ``"\\n".join(...)``
    semantics).

    Args:
        objects: Iterable of Python objects to serialize.
        **kwargs: Keyword arguments forwarded to :func:`json.dumps`.

    Returns:
        JSONL string (one JSON value per line).
    """
    return "\n".join(json.dumps(obj, **kwargs) for obj in objects)

dump_lines(objects, fp, **kwargs)

Serialize a list of Python objects to a JSONL file.

Parameters:

Name Type Description Default
objects list[Any]

Iterable of Python objects to serialize.

required
fp IO[str]

A text file-like object to write to.

required
**kwargs Any

Keyword arguments forwarded to :func:json.dumps.

{}
Source code in jsonx/jsonx.py
def dump_lines(
    objects: list[Any],
    fp: IO[str],
    **kwargs: Any,
) -> None:
    """Serialize a list of Python objects to a JSONL file.

    Args:
        objects: Iterable of Python objects to serialize.
        fp: A text file-like object to write to.
        **kwargs: Keyword arguments forwarded to :func:`json.dumps`.
    """
    fp.write(dumps_lines(objects, **kwargs))
    fp.write("\n")