nipoppy.utils.json5

Utilities to edit JSON5 objects while preserving comments.

Overview

This module applies targeted edits to JSON5 text without reformatting it, so comments and existing layout survive. Edits work in two phases:

  1. Locate the source span (start/end character indices) of the object, member, or value that an edit targets.

  2. Splice new text into that span, leaving everything else byte-for-byte unchanged.

The code is organized in layers, from lowest to highest level:

  • _Scanner: a cursor over the source text. Each method performs a single scanning job (skip trivia, find a string end, match a bracket, find a value end) and advances the cursor in place.

  • _parse_object_members / _find_root_object_span: structural parsing that produces _ObjectMember spans.

  • Editing primitives (_get_line_indent, _format_member_text, _insert_member_into_object): build and splice new member text.

  • Navigation helpers (_find_member_by_key, _get_object_value_span) and the high-level setter (_set_value_at_key_path) that resolves a key path and writes a value.

  • Public API: update_json5_text() and update_json5_file().

Module Contents

nipoppy.utils.json5.update_json5_file(fpath, updates)

Apply (key_path, value) updates to a JSON5 file in place.

Parameters:
Return type:

None

nipoppy.utils.json5.update_json5_text(text, updates)

Apply updates to JSON5 text while preserving comments and formatting.

Input and output are validated with json5.loads. Updates are applied in order, and each update sees the result of previous edits.

Parameters:
  • updates (Iterable[tuple[list[str], Any]]) – (key_path, value) tuples. key_path is a list of nested keys whose final key is set to value.

  • text (str)

Returns:

Updated JSON5 text.

Return type:

str

Raises:

ValueError – If the input or resulting text is invalid JSON5, or a key path is empty.