Skip to content

AClon314/jsonc-sdict

Repository files navigation

简中文档

logo

jsonc_sdict 即典

PyPI - Version

Round-trip comments for JSONC/HJSON, with dict-like APIs that stay simple & easy for app config editing.

  • Keep comments on read and write (loads → edit → restore).
  • Work with nested structures via sdictdeepmerge + deepdiff + benedict
  • Use weak-reference ordered containers via weakList/OrderedWeakSet.

Comments are data too, just like codes are data too by John von Neumann

Warning

This project is currently alpha (0.1.x) and still being refactored.

Usage

Install

pip install jsonc-sdict

For local development:

pip install -e ".[dev]"

Quick start

import json
import hjson
from jsonc_sdict import jsonc, AS_DATA

raw = """
// header
{
  "a": 1, // inline
  "b": 2
}
// footer
"""

def loads(self, obj):
    return hjson.loads(obj, ...) # pre-fill your custom args here

jc = jsoncDict(raw, loads, dumps=hjson.dumps)
jc.insert_comment(
    {
        "/*\\nnew-block": "multi\\nline\\n",
        "//\\nnew-line-above": "line above b\\n",
        "//this-is-data" + AS_DATA: ["not a comment key"],
    },
    key="b",
)

print(jc.full)

Comment keyname rule

jsonc stores comments as synthetic keys in the underlying mapping:

<prefix><position-marker><id><SEED>
  • SEED is auto-appended to mark an internal comment key.
  • Add AS_DATA suffix to force a key starting with comment prefix to be treated as normal data.

Common forms:

Internal key prefix Means Restored shape
// single-line comment, inline mode after current value/comma
//\n single-line comment, line-above mode independent line before next key/value
/* block comment (default) inline block comment
/*\n block comment with trailing newline mode rendered with line break behavior
/*, block comment before comma placed before comma of current item
/*k block comment before key slot before JSON key token
/*: block comment before colon slot between key and value
/*v block comment before value slot after colon, before value
/- slash_dash comment comments out a whole subtree (KDL-like style)

Example mapping shape:

{
    "//0<SEED>": ' "": null,',
    "0": 0,
    "//1<SEED>": " 0",
    "//\n2<SEED>": ' "1": 1,/* 1 */',
    "/*,3<SEED>": " 2 ",
    "2": 2,
    "/*\n4<SEED>": " 👻 ",
    "/*v6<SEED>": " 6 ",
    "6//": 6,
    "/*k7<SEED>": " 7 ",
    "7": 7,
    "/-node<SEED>": {"ignored": "slash_dash comment"},
    "node": {"kept": "real data"},
}

Edge cases

Invalid JSONC examples:

// /* this is still single-line comment
so this line is illegal */
/* // this is block comment */ trailing-text-is-illegal

Develop

env

LOG=DEBUG enables debug-level logging in project loggers.

Common setup:

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
LOG=DEBUG pytest -q

Internal design

jsonc

  • Inline comment (//...): stored as //<id><SEED>, restored near the current item.
  • Line-above comment (//\n...): stored as line-above mode, restored before next item.
  • Block comment (/*...*/): stored with mode markers (/*, /*,, /*k, /*:, /*v, /*\n) to preserve placement.
  • slash_dash comment (/-name): special key style that comments out a full subtree, similar to KDL config style.

sdict (common pitfalls)

  • sdict wraps both mapping and iterable nodes; nested access may return sdict views, not raw dict/list.
  • Cache fields (for example body, body_restored) rely on mutation hooks; bypassing APIs can leave stale cache.
  • dfs() warns against mutating yielded data during iteration.
  • insert(update, key=...|index=...) is ordering-oriented: it inserts by reordering keys after update.

weakList (common pitfalls)

  • Items must support both __hash__ and weak references (__weakref__); built-in int/str/list/dict do not qualify.
  • Weak references can disappear when no strong references exist; list length can shrink unexpectedly.
  • WeakList(noRepeat=True) is not identical to OrderedWeakSet: repeated append/insert can move item position.

Related projects

json loads()

pypi commits issues about lack
spyoungtech/json-five ⭐ 🕒 LAST🕒 🎯 🎯close Python JSON5 parser with round-trip preservation of comments can keep comment, but in AST-tree style with lots of re-defined concepts (e.g: BlockComment/wsc_before)
tusharsadhwani/json5kit ⭐ 🕒 LAST🕒 🎯 🎯close A Roundtrip parser and CST for JSON, JSONC and JSON5.
dpranke/pyjson5 ⭐ 🕒 LAST🕒 🎯 🎯close A Python implementation of the JSON5 data format
austinyu/ujson5 ⭐ 🕒 LAST🕒 🎯 🎯close A fast JSON5 encoder/decoder for Python
qvecs/qjson5 ⭐ 🕒 LAST🕒 🎯 🎯close 📎 A quick JSON5 implementation written in C, with Python bindings.

other format that support round-trip

About

keep comment(round-trip) when read & write jsonc/hjson, sdict with extra context(parent/keypath), weakList & OrderedWeakSet

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages