| Name | headson JSON |
| Version |
0.6.2
JSON |
| download |
| home_page | None |
| Summary | Budget‑constrained JSON preview renderer (Python bindings) |
| upload_time | 2025-11-01 10:16:37 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.10 |
| license | None |
| keywords |
json
preview
summarize
cli
bindings
|
| VCS |
|
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
<h1 align="center">
<img src="https://raw.githubusercontent.com/kantord/headson/main/docs/assets/logo.svg" alt="headson" width="221" />
</h1>
<p align="center">
<img src="https://raw.githubusercontent.com/kantord/headson/main/docs/assets/tapes/demo.gif" alt="Terminal demo" width="1560" height="900" />
<br/>
</p>
Head/tail for JSON and YAML — but structure‑aware. Get a compact preview that shows both the shape and representative values of your data, all within a strict character budget.
Available as:
- CLI (see [Usage](#usage))
- Python library (see [Python Bindings](#python-bindings))
## Install
Using Cargo:
cargo install headson
From source:
cargo build --release
target/release/headson --help
## Features
- Budgeted output: specify exactly how much you want to see
- Output formats: `auto | json | yaml`
- Styles: `strict | default | detailed`
- JSON family: `strict` → strict JSON, `default` → human‑friendly Pseudo, `detailed` → JS with inline comments
- YAML: always YAML; `strict` has no comments, `default` uses “# …”, `detailed` uses “# N more …”
- Multiple inputs: preview many files at once with a shared or per‑file budget
- Fast: processes gigabyte‑scale files in seconds (mostly disk‑bound)
- Available as a CLI app and as a Python library
## Fits into command line workflows
If you’re comfortable with tools like `head` and `tail`, use `headson` when you want a quick, structured peek into a JSON file without dumping the entire thing.
- `head`/`tail` operate on bytes/lines - their output is not optimized for tree structures
- `jq` you need to craft filters to preview large JSON files
- `headson` is like head/tail for trees: zero config but it keeps structure and represents content as much as possible
## Usage
headson [FLAGS] [INPUT...]
- INPUT (optional, repeatable): file path(s). If omitted, reads from stdin. Multiple input files are supported.
- Prints the preview to stdout. On parse errors, exits non‑zero and prints an error to stderr.
Common flags:
- `-n, --budget <BYTES>`: per‑file output budget. For multiple inputs, default total budget is `<BYTES> * number_of_inputs`.
- `-N, --global-budget <BYTES>`: total output budget across all inputs. With `--budget`, the effective total is the smaller of the two.
- `-f, --format <auto|json|yaml>`: output format (default: `auto`).
- Auto: stdin → JSON family; filesets → per‑file based on extension (`.json` → JSON family, `.yaml`/`.yml` → YAML).
- `-t, --template <strict|default|detailed>`: output style (default: `default`).
- JSON family: `strict` → strict JSON; `default` → Pseudo; `detailed` → JS with inline comments.
- YAML: always YAML; style only affects comments (`strict` none, `default` “# …”, `detailed` “# N more …”).
- `-i, --input-format <json|yaml>`: ingestion format (default: `json`). For filesets in `auto` format, ingestion is chosen by extensions.
- `-m, --compact`: no indentation, no spaces, no newlines
- `--no-newline`: single line output
- `--no-space`: no space after `:` in objects
- `--indent <STR>`: indentation unit (default: two spaces)
- `--string-cap <N>`: max graphemes to consider per string (default: 500)
- `--head`: prefer the beginning of arrays when truncating (keep first N). Strings are unaffected. Display styles place omission markers accordingly; strict JSON remains unannotated. Mutually exclusive with `--tail`.
- `--tail`: prefer the end of arrays when truncating (keep last N). Strings are unaffected. Display styles place omission markers accordingly; strict JSON remains unannotated. Mutually exclusive with `--head`.
Notes:
- Multiple inputs:
- With newlines enabled, file sections are rendered with human‑readable headers. In compact/single‑line modes, headers are omitted.
- In `--format auto`, each file uses its own best format: JSON family for `.json`, YAML for `.yaml`/`.yml`.
- `--global-budget` may truncate or omit entire files to respect the total budget.
- The tool finds the largest preview that fits the budget; even if extremely tight, you still get a minimal, valid preview.
- Directories and binary files are ignored; a notice is printed to stderr for each. Stdin reads the stream as‑is.
- Head vs Tail sampling: these options bias which part of arrays are kept before rendering. Display styles may still insert internal gap markers to honor very small budgets; strict JSON stays unannotated.
Quick one‑liners:
- Peek a big JSON stream (keeps structure):
zstdcat huge.json.zst | headson -n 800 -f json -t default
- Many files with a fixed overall size:
headson -N 1200 -f json -t strict logs/*.json
- Glance at a file, JavaScript‑style comments for omissions:
headson -n 400 -f json -t detailed data.json
- YAML with detailed comments:
headson -n 400 -f yaml -t detailed config.yaml
Show help:
headson --help
## Examples: head vs headson
Input:
```json
{"users":[{"id":1,"name":"Ana","roles":["admin","dev"]},{"id":2,"name":"Bo"}],"meta":{"count":2,"source":"db"}}
```
Naive cut (can break mid‑token):
```bash
jq -c . users.json | head -c 80
# {"users":[{"id":1,"name":"Ana","roles":["admin","dev"]},{"id":2,"name":"Bo"}],"me
```
Structured preview with headson (JSON family, default style → Pseudo):
```bash
headson -n 120 -f json -t default users.json
# {
# users: [
# { id: 1, name: "Ana", roles: [ "admin", … ] },
# …
# ]
# meta: { count: 2, … }
# }
```
Machine‑readable preview (JSON family, strict style → strict JSON):
```bash
headson -n 120 -f json -t strict users.json
# {"users":[{"id":1,"name":"Ana","roles":["admin"]}],"meta":{"count":2}}
```
## Terminal Demos
Regenerate locally:
- Place tapes under docs/tapes (e.g., docs/tapes/demo.tape)
- Run: cargo make tapes
- Outputs are written to docs/assets/tapes
## Python Bindings
A thin Python extension module is available on PyPI as `headson`.
- Install: `pip install headson` (ABI3 wheels for Python 3.10+ on Linux/macOS/Windows).
- API:
- `headson.summarize(text: str, *, format: str = "auto", style: str = "default", input_format: str = "json", character_budget: int | None = None, skew: str = "balanced") -> str`
- `format`: `"auto" | "json" | "yaml"` (auto maps to JSON family for single inputs)
- `style`: `"strict" | "default" | "detailed"`
- `input_format`: `"json" | "yaml"` (ingestion)
- `character_budget`: maximum output size in characters (default: 500)
- `skew`: `"balanced" | "head" | "tail"` (affects display styles; strict JSON remains unannotated)
Examples:
```python
import json
import headson
data = {"foo": [1, 2, 3], "bar": {"x": "y"}}
preview = headson.summarize(json.dumps(data), format="json", style="strict", character_budget=200)
print(preview)
# Prefer the tail of arrays (annotations show with style="default"/"detailed")
print(
headson.summarize(
json.dumps(list(range(100))),
format="json",
style="detailed",
character_budget=80,
skew="tail",
)
)
# YAML support
doc = "root:\n items: [1,2,3,4,5,6,7,8,9,10]\n"
print(headson.summarize(doc, format="yaml", style="default", input_format="yaml", character_budget=60))
```
# Algorithm

## Footnotes
- <sup><b>[1]</b></sup> <b>Optimized tree representation</b>: An arena‑style tree stored in flat, contiguous buffers. Each node records its kind and value plus index ranges into shared child and key arrays. Arrays are ingested in a single pass and may be deterministically pre‑sampled: the first element is always kept; additional elements are selected via a fixed per‑index inclusion test; for kept elements, original indices are stored and full lengths are counted. This enables accurate omission info and internal gap markers later, while minimizing pointer chasing.
- <sup><b>[2]</b></sup> <b>Priority order</b>: Nodes are scored so previews surface representative structure and values first. Arrays can favor head/mid/tail coverage (default) or strictly the head; tail preference flips head/tail when configured. Object properties are ordered by key, and strings expand by grapheme with early characters prioritized over very deep expansions.
- <sup><b>[3]</b></sup> <b>Choose top N nodes (binary search)</b>: Iteratively picks N so that the rendered preview fits within the character budget, looping between “choose N” and a render attempt to converge quickly.
- <sup><b>[4]</b></sup> <b>Render attempt</b>: Serializes the currently included nodes using the selected template. Omission summaries and per-file section headers appear in display templates (pseudo/js); json remains strict. For arrays, display templates may insert internal gap markers between non‑contiguous kept items using original indices.
- <sup><b>[5]</b></sup> <b>Diagram source</b>: The Algorithm diagram is generated from `docs/diagrams/algorithm.mmd`. Regenerate the SVG with `cargo make diagrams` before releasing.
## License
MIT
Raw data
{
"_id": null,
"home_page": null,
"name": "headson",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "json, preview, summarize, cli, bindings",
"author": null,
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/f8/85/e40550758221e27bdb2fcdd854d3496566886544e98f880eefd75a3a8081/headson-0.6.2.tar.gz",
"platform": null,
"description": "<h1 align=\"center\">\n <img src=\"https://raw.githubusercontent.com/kantord/headson/main/docs/assets/logo.svg\" alt=\"headson\" width=\"221\" />\n</h1>\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/kantord/headson/main/docs/assets/tapes/demo.gif\" alt=\"Terminal demo\" width=\"1560\" height=\"900\" />\n <br/>\n</p>\n\nHead/tail for JSON and YAML \u2014 but structure\u2011aware. Get a compact preview that shows both the shape and representative values of your data, all within a strict character budget.\n\nAvailable as:\n- CLI (see [Usage](#usage))\n- Python library (see [Python Bindings](#python-bindings))\n\n## Install\n\nUsing Cargo:\n\n cargo install headson\n\nFrom source:\n\n cargo build --release\n target/release/headson --help\n\n\n## Features\n\n- Budgeted output: specify exactly how much you want to see\n- Output formats: `auto | json | yaml`\n - Styles: `strict | default | detailed`\n - JSON family: `strict` \u2192 strict JSON, `default` \u2192 human\u2011friendly Pseudo, `detailed` \u2192 JS with inline comments\n - YAML: always YAML; `strict` has no comments, `default` uses \u201c# \u2026\u201d, `detailed` uses \u201c# N more \u2026\u201d\n- Multiple inputs: preview many files at once with a shared or per\u2011file budget\n- Fast: processes gigabyte\u2011scale files in seconds (mostly disk\u2011bound)\n- Available as a CLI app and as a Python library\n\n## Fits into command line workflows\n\nIf you\u2019re comfortable with tools like `head` and `tail`, use `headson` when you want a quick, structured peek into a JSON file without dumping the entire thing.\n\n- `head`/`tail` operate on bytes/lines - their output is not optimized for tree structures\n- `jq` you need to craft filters to preview large JSON files\n- `headson` is like head/tail for trees: zero config but it keeps structure and represents content as much as possible \n\n## Usage\n\n headson [FLAGS] [INPUT...]\n\n- INPUT (optional, repeatable): file path(s). If omitted, reads from stdin. Multiple input files are supported.\n- Prints the preview to stdout. On parse errors, exits non\u2011zero and prints an error to stderr.\n\nCommon flags:\n\n- `-n, --budget <BYTES>`: per\u2011file output budget. For multiple inputs, default total budget is `<BYTES> * number_of_inputs`.\n- `-N, --global-budget <BYTES>`: total output budget across all inputs. With `--budget`, the effective total is the smaller of the two.\n- `-f, --format <auto|json|yaml>`: output format (default: `auto`).\n - Auto: stdin \u2192 JSON family; filesets \u2192 per\u2011file based on extension (`.json` \u2192 JSON family, `.yaml`/`.yml` \u2192 YAML).\n- `-t, --template <strict|default|detailed>`: output style (default: `default`).\n - JSON family: `strict` \u2192 strict JSON; `default` \u2192 Pseudo; `detailed` \u2192 JS with inline comments.\n - YAML: always YAML; style only affects comments (`strict` none, `default` \u201c# \u2026\u201d, `detailed` \u201c# N more \u2026\u201d).\n- `-i, --input-format <json|yaml>`: ingestion format (default: `json`). For filesets in `auto` format, ingestion is chosen by extensions.\n- `-m, --compact`: no indentation, no spaces, no newlines\n- `--no-newline`: single line output\n- `--no-space`: no space after `:` in objects\n- `--indent <STR>`: indentation unit (default: two spaces)\n- `--string-cap <N>`: max graphemes to consider per string (default: 500)\n- `--head`: prefer the beginning of arrays when truncating (keep first N). Strings are unaffected. Display styles place omission markers accordingly; strict JSON remains unannotated. Mutually exclusive with `--tail`.\n- `--tail`: prefer the end of arrays when truncating (keep last N). Strings are unaffected. Display styles place omission markers accordingly; strict JSON remains unannotated. Mutually exclusive with `--head`.\n\nNotes:\n\n- Multiple inputs:\n - With newlines enabled, file sections are rendered with human\u2011readable headers. In compact/single\u2011line modes, headers are omitted.\n - In `--format auto`, each file uses its own best format: JSON family for `.json`, YAML for `.yaml`/`.yml`.\n - `--global-budget` may truncate or omit entire files to respect the total budget.\n - The tool finds the largest preview that fits the budget; even if extremely tight, you still get a minimal, valid preview.\n - Directories and binary files are ignored; a notice is printed to stderr for each. Stdin reads the stream as\u2011is.\n - Head vs Tail sampling: these options bias which part of arrays are kept before rendering. Display styles may still insert internal gap markers to honor very small budgets; strict JSON stays unannotated.\n\nQuick one\u2011liners:\n\n- Peek a big JSON stream (keeps structure):\n\n zstdcat huge.json.zst | headson -n 800 -f json -t default\n\n- Many files with a fixed overall size:\n\n headson -N 1200 -f json -t strict logs/*.json\n\n- Glance at a file, JavaScript\u2011style comments for omissions:\n\n headson -n 400 -f json -t detailed data.json\n\n- YAML with detailed comments:\n\n headson -n 400 -f yaml -t detailed config.yaml\n\nShow help:\n\n headson --help\n\n## Examples: head vs headson\n\nInput:\n\n```json\n{\"users\":[{\"id\":1,\"name\":\"Ana\",\"roles\":[\"admin\",\"dev\"]},{\"id\":2,\"name\":\"Bo\"}],\"meta\":{\"count\":2,\"source\":\"db\"}}\n```\n\nNaive cut (can break mid\u2011token):\n\n```bash\njq -c . users.json | head -c 80\n# {\"users\":[{\"id\":1,\"name\":\"Ana\",\"roles\":[\"admin\",\"dev\"]},{\"id\":2,\"name\":\"Bo\"}],\"me\n```\n\nStructured preview with headson (JSON family, default style \u2192 Pseudo):\n\n```bash\nheadson -n 120 -f json -t default users.json\n# {\n# users: [\n# { id: 1, name: \"Ana\", roles: [ \"admin\", \u2026 ] },\n# \u2026\n# ]\n# meta: { count: 2, \u2026 }\n# }\n```\n\nMachine\u2011readable preview (JSON family, strict style \u2192 strict JSON):\n\n```bash\nheadson -n 120 -f json -t strict users.json\n# {\"users\":[{\"id\":1,\"name\":\"Ana\",\"roles\":[\"admin\"]}],\"meta\":{\"count\":2}}\n```\n\n## Terminal Demos\n\nRegenerate locally:\n\n- Place tapes under docs/tapes (e.g., docs/tapes/demo.tape)\n- Run: cargo make tapes\n- Outputs are written to docs/assets/tapes\n\n## Python Bindings\n\nA thin Python extension module is available on PyPI as `headson`.\n\n- Install: `pip install headson` (ABI3 wheels for Python 3.10+ on Linux/macOS/Windows).\n- API:\n - `headson.summarize(text: str, *, format: str = \"auto\", style: str = \"default\", input_format: str = \"json\", character_budget: int | None = None, skew: str = \"balanced\") -> str`\n - `format`: `\"auto\" | \"json\" | \"yaml\"` (auto maps to JSON family for single inputs)\n - `style`: `\"strict\" | \"default\" | \"detailed\"`\n - `input_format`: `\"json\" | \"yaml\"` (ingestion)\n - `character_budget`: maximum output size in characters (default: 500)\n - `skew`: `\"balanced\" | \"head\" | \"tail\"` (affects display styles; strict JSON remains unannotated)\n\nExamples:\n\n```python\nimport json\nimport headson\n\ndata = {\"foo\": [1, 2, 3], \"bar\": {\"x\": \"y\"}}\npreview = headson.summarize(json.dumps(data), format=\"json\", style=\"strict\", character_budget=200)\nprint(preview)\n\n# Prefer the tail of arrays (annotations show with style=\"default\"/\"detailed\")\nprint(\n headson.summarize(\n json.dumps(list(range(100))),\n format=\"json\",\n style=\"detailed\",\n character_budget=80,\n skew=\"tail\",\n )\n)\n\n# YAML support\ndoc = \"root:\\n items: [1,2,3,4,5,6,7,8,9,10]\\n\"\nprint(headson.summarize(doc, format=\"yaml\", style=\"default\", input_format=\"yaml\", character_budget=60))\n```\n\n# Algorithm\n\n\n\n## Footnotes\n - <sup><b>[1]</b></sup> <b>Optimized tree representation</b>: An arena\u2011style tree stored in flat, contiguous buffers. Each node records its kind and value plus index ranges into shared child and key arrays. Arrays are ingested in a single pass and may be deterministically pre\u2011sampled: the first element is always kept; additional elements are selected via a fixed per\u2011index inclusion test; for kept elements, original indices are stored and full lengths are counted. This enables accurate omission info and internal gap markers later, while minimizing pointer chasing.\n - <sup><b>[2]</b></sup> <b>Priority order</b>: Nodes are scored so previews surface representative structure and values first. Arrays can favor head/mid/tail coverage (default) or strictly the head; tail preference flips head/tail when configured. Object properties are ordered by key, and strings expand by grapheme with early characters prioritized over very deep expansions.\n - <sup><b>[3]</b></sup> <b>Choose top N nodes (binary search)</b>: Iteratively picks N so that the rendered preview fits within the character budget, looping between \u201cchoose N\u201d and a render attempt to converge quickly.\n - <sup><b>[4]</b></sup> <b>Render attempt</b>: Serializes the currently included nodes using the selected template. Omission summaries and per-file section headers appear in display templates (pseudo/js); json remains strict. For arrays, display templates may insert internal gap markers between non\u2011contiguous kept items using original indices.\n - <sup><b>[5]</b></sup> <b>Diagram source</b>: The Algorithm diagram is generated from `docs/diagrams/algorithm.mmd`. Regenerate the SVG with `cargo make diagrams` before releasing.\n\n## License\n\nMIT\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Budget\u2011constrained JSON preview renderer (Python bindings)",
"version": "0.6.2",
"project_urls": null,
"split_keywords": [
"json",
" preview",
" summarize",
" cli",
" bindings"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "17d6a63603b51a81be596066e927896cc14975f33cddf3714e7d1865d916a41b",
"md5": "da56d36aeea45ea15ddee3a3bf8e2253",
"sha256": "a488b20f8efec59216814b08d8f69325a20c52278e1518d690e90977ca319f6b"
},
"downloads": -1,
"filename": "headson-0.6.2-cp310-abi3-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "da56d36aeea45ea15ddee3a3bf8e2253",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.10",
"size": 402333,
"upload_time": "2025-11-01T10:16:36",
"upload_time_iso_8601": "2025-11-01T10:16:36.389638Z",
"url": "https://files.pythonhosted.org/packages/17/d6/a63603b51a81be596066e927896cc14975f33cddf3714e7d1865d916a41b/headson-0.6.2-cp310-abi3-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "27043edc704f1a6854e79271d9a3cc8cf184f9abcaf862efa4d2ef4be3c57d64",
"md5": "0a6be8a11dba2c375b8b9fa8571c0b0b",
"sha256": "b955f6898365549a2fa4e5ee1ab33addfc1ed83d4818c4bfc20c05eed15d04a3"
},
"downloads": -1,
"filename": "headson-0.6.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "0a6be8a11dba2c375b8b9fa8571c0b0b",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.10",
"size": 469242,
"upload_time": "2025-11-01T10:17:42",
"upload_time_iso_8601": "2025-11-01T10:17:42.032540Z",
"url": "https://files.pythonhosted.org/packages/27/04/3edc704f1a6854e79271d9a3cc8cf184f9abcaf862efa4d2ef4be3c57d64/headson-0.6.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "71499f38cf6da4ae74f69401175bfd6f8c561224990b23cc396eb9d8da6855e2",
"md5": "7da98d1cbb11aa0cb7e31d32e956231d",
"sha256": "c0c95c3e211de480a6861ea8c4cf89413ac7a9815d3cc49ac988f84dac701407"
},
"downloads": -1,
"filename": "headson-0.6.2-cp310-abi3-win_amd64.whl",
"has_sig": false,
"md5_digest": "7da98d1cbb11aa0cb7e31d32e956231d",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.10",
"size": 358566,
"upload_time": "2025-11-01T10:17:58",
"upload_time_iso_8601": "2025-11-01T10:17:58.381955Z",
"url": "https://files.pythonhosted.org/packages/71/49/9f38cf6da4ae74f69401175bfd6f8c561224990b23cc396eb9d8da6855e2/headson-0.6.2-cp310-abi3-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f885e40550758221e27bdb2fcdd854d3496566886544e98f880eefd75a3a8081",
"md5": "3c1750abad426aef9ba524f15007f0d9",
"sha256": "1d0a6644ec65ff74773098dd2074a4b03dae98e049f9ab9c4a88226d4c311cd8"
},
"downloads": -1,
"filename": "headson-0.6.2.tar.gz",
"has_sig": false,
"md5_digest": "3c1750abad426aef9ba524f15007f0d9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 3546978,
"upload_time": "2025-11-01T10:16:37",
"upload_time_iso_8601": "2025-11-01T10:16:37.769302Z",
"url": "https://files.pythonhosted.org/packages/f8/85/e40550758221e27bdb2fcdd854d3496566886544e98f880eefd75a3a8081/headson-0.6.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-01 10:16:37",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "headson"
}