コンテンツにスキップ

pytilpack.jsonc

pytilpack.jsonc

JSONC(JSON with Comments)関連。

load(source, encoding='utf-8', errors='replace', strict=False, **kwargs)

JSONCファイルの読み込み。

ソースコード位置: pytilpack/jsonc.py
def load(
    source: pytilpack.io.PathOrIO,
    encoding: str = "utf-8",
    errors: str = "replace",
    strict: bool = False,
    **kwargs,
) -> typing.Any:
    """JSONCファイルの読み込み。"""
    try:
        return loads(pytilpack.io.read_text(source, encoding=encoding, errors=errors), **kwargs)
    except FileNotFoundError:
        if strict:
            raise
        return {}

loads(text, **kwargs)

JSONC文字列のパース。

ソースコード位置: pytilpack/jsonc.py
def loads(text: str, **kwargs) -> typing.Any:
    """JSONC文字列のパース。"""
    return json.loads(_remove_trailing_commas(_remove_comments(text)), **kwargs)

edit(text, updates, ensure_ascii=False, default=None, **dumps_kwargs)

JSONC文字列中の指定パスの値を書き換えつつコメント・空行・インデントを維持する。

updatesのキーはパス(オブジェクトキー名の文字列または配列インデックスの整数の並び)、 値は書き込む新しいPythonオブジェクトとする。空タプルはルート全体を指す。 値の書き換えのみを対象とし、キーの追加・削除・配列要素の追加は扱わない。 書き換え後の値のシリアライズはjson.dumpsに委譲するため、 ensure_asciidefaultなどの追加キーワード引数はそのまま渡す。

存在しないパスを指定した場合はKeyError(オブジェクト)またはIndexError(配列)が発生する。 パスの途中で辿った値がオブジェクト・配列でない場合はTypeErrorが発生する。

引数:

名前 タイプ デスクリプション デフォルト
text str

元のJSONC文字列。

必須
updates Mapping[_Path, Any]

パスから新しい値へのマッピング。

必須
ensure_ascii bool

json.dumpsへ渡すフラグ。既定はFalse

False
default Callable[[Any], Any] | None

json.dumpsへ渡すdefaultコールバック。

None
**dumps_kwargs Any

json.dumpsへ渡す追加キーワード引数。

{}

戻り値:

タイプ デスクリプション
str

更新後のJSONC文字列。

ソースコード位置: pytilpack/jsonc.py
def edit(
    text: str,
    updates: typing.Mapping[_Path, typing.Any],
    ensure_ascii: bool = False,
    default: typing.Callable[[typing.Any], typing.Any] | None = None,
    **dumps_kwargs: typing.Any,
) -> str:
    """JSONC文字列中の指定パスの値を書き換えつつコメント・空行・インデントを維持する。

    ``updates``のキーはパス(オブジェクトキー名の文字列または配列インデックスの整数の並び)、
    値は書き込む新しいPythonオブジェクトとする。空タプルはルート全体を指す。
    値の書き換えのみを対象とし、キーの追加・削除・配列要素の追加は扱わない。
    書き換え後の値のシリアライズは``json.dumps``に委譲するため、
    ``ensure_ascii``・``default``などの追加キーワード引数はそのまま渡す。

    存在しないパスを指定した場合は``KeyError``(オブジェクト)または``IndexError``(配列)が発生する。
    パスの途中で辿った値がオブジェクト・配列でない場合は``TypeError``が発生する。

    Args:
        text: 元のJSONC文字列。
        updates: パスから新しい値へのマッピング。
        ensure_ascii: ``json.dumps``へ渡すフラグ。既定は``False``。
        default: ``json.dumps``へ渡す``default``コールバック。
        **dumps_kwargs: ``json.dumps``へ渡す追加キーワード引数。

    Returns:
        更新後のJSONC文字列。

    """
    root = _Parser(text).parse()
    replacements: list[tuple[int, int, str]] = []
    for path, value in updates.items():
        node = _resolve(root, tuple(path))
        dumped = json.dumps(value, ensure_ascii=ensure_ascii, default=default, **dumps_kwargs)
        replacements.append((node.start, node.end, dumped))
    replacements.sort(key=lambda r: r[0], reverse=True)
    # オフセット重複の検出(同一位置または包含関係を持つ書き換えは順序に依存し曖昧なため拒否する)
    for i in range(len(replacements) - 1):
        curr_start = replacements[i][0]
        next_end = replacements[i + 1][1]
        if curr_start < next_end:
            raise ValueError("updates contains overlapping paths")
    result = text
    for start, end, new_text in replacements:
        result = result[:start] + new_text + result[end:]
    return result

edit_file(path, updates, encoding='utf-8', errors='replace', ensure_ascii=False, default=None, **dumps_kwargs)

JSONCファイルをeditで書き換えて上書き保存する。

コメント・空行・インデントを維持したままファイル内の値を差し替える。

ソースコード位置: pytilpack/jsonc.py
def edit_file(
    path: pytilpack.io.PathOrIO,
    updates: typing.Mapping[_Path, typing.Any],
    encoding: str = "utf-8",
    errors: str = "replace",
    ensure_ascii: bool = False,
    default: typing.Callable[[typing.Any], typing.Any] | None = None,
    **dumps_kwargs: typing.Any,
) -> None:
    """JSONCファイルを``edit``で書き換えて上書き保存する。

    コメント・空行・インデントを維持したままファイル内の値を差し替える。

    """
    original = pytilpack.io.read_text(path, encoding=encoding, errors=errors)
    updated = edit(original, updates, ensure_ascii=ensure_ascii, default=default, **dumps_kwargs)
    pytilpack.io.write_text(path, updated, encoding=encoding, errors=errors)