Dot-path access, mutation, and flattening for deeply nested dict/JSON data, with clear error messages.
Project description
grabmonkey
Dot-path access, mutation, and flattening for deeply nested dict/JSON data — with error messages that tell you exactly which level failed.
Stop writing this:
data.get("response", {}).get("results", [{}])[0].get("metadata", {}).get("created_at", "")
Write this:
from grabmonkey import grab
grab(data, "response.results[0].metadata.created_at", default="")
Install
pip install grabmonkey
Requires Python 3.11+. No runtime dependencies.
Quick start
from grabmonkey import grab, grab_many, put, delete, flatten, unflatten
data = {"response": {"results": [{"metadata": {"id": 1, "created_at": "2026"}}]}}
# Read, any depth
grab(data, "response.results[0].metadata.created_at") # "2026"
# Safe default instead of an exception
grab(data, "response.results[0].missing", default="") # ""
# Type coercion on access
grab({"count": "42"}, "count", as_type=int) # 42
# Wildcards over lists
grab({"items": [{"n": 1}, {"n": 2}]}, "items[*].n") # [1, 2]
# Batch access
grab_many(data, {"id": "response.results[0].metadata.id"}) # {"id": 1}
# Set and delete (mutates in place, creates intermediate containers)
d = {}
put(d, "a.b[2].c", 9) # {"a": {"b": [None, None, {"c": 9}]}}
delete(d, "a.b[2].c") # {"a": {"b": [None, None, {}]}}
delete(d, "a.b[2]", prune=True) # {"a": {"b": [None, None]}} (prune drops empties)
# Flatten / unflatten
flatten({"a": {"b": [1, 2]}}) # {"a.b[0]": 1, "a.b[1]": 2}
unflatten({"a.b[0]": 1, "a.b[1]": 2}) # {"a": {"b": [1, 2]}}
Clear errors
grab(data, "response.results[0].nope")
# grabmonkey.errors.PathError:
# Path 'response.results[0].nope' failed at 'nope':
# key not found in dict with keys ['metadata']
PathError (a LookupError) means a structural miss — the case default=
absorbs. PathSyntaxError means a malformed path string. CoercionError means
the value was found but as_type could not convert it. The last two are not
absorbed by default=, on purpose.
Path syntax
| Syntax | Meaning |
|---|---|
a.b.c |
dict key or object attribute |
items[0], items[-1] |
sequence index |
items[*] |
every element of a sequence / value of a mapping |
data['weird.key'] |
quoted key for keys with dots/brackets/spaces |
Works on dicts, lists, dataclasses, named tuples, and any object with attribute access. Strings and bytes are treated as leaf values, not navigable containers (see LIMITATIONS.md).
CLI
Reads JSON from a file (--input) or stdin, prints JSON:
echo '{"user":{"name":"Alice"}}' | grabmonkey grab user.name # "Alice"
echo '{"a":{"b":1}}' | grabmonkey flatten # {"a.b": 1}
grabmonkey grab metadata.id --input response.json
Using with AI assistants
See SKILL.md for an LLM-consumable reference (decision table, worked examples, anti-patterns). See LIMITATIONS.md for deliberate design tradeoffs.
Development & review
grabmonkey is tested and reviewed under a portable review kit:
- CONTRIBUTING.md — testing philosophy and the competitive multi-model review-panel process.
- LIMITATIONS.md — deliberate tradeoffs reviewers should not re-litigate (read before "fixing" surprising behaviour).
- RELEASE_READINESS.md — the release rubric; run
python scripts/readiness.pyfor the score and convergence verdict. - REVIEW_HISTORY.md — the panel-by-panel trajectory.
review-kit/— the pristine, project-agnostic templates the above were derived from (inert to the project's own checks).
pip install -e ".[dev]"
pytest -q && ruff check src tests && mypy
python scripts/readiness.py
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grabmonkey-1.1.0.tar.gz.
File metadata
- Download URL: grabmonkey-1.1.0.tar.gz
- Upload date:
- Size: 33.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26640fc4d778c3a8994377c5d818ad4fe541501c157f6aa648dede2d8482fcfd
|
|
| MD5 |
7912c022945f537b21699098d14dbbb7
|
|
| BLAKE2b-256 |
457023e535ba0ba4fda8f68b91116b187a81c588ec9a66a1dffce2ea3a2bf28f
|
File details
Details for the file grabmonkey-1.1.0-py3-none-any.whl.
File metadata
- Download URL: grabmonkey-1.1.0-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01eda7b32bf02fb05751e306d4211858e4e30d1669283126587d95bf65c4cf36
|
|
| MD5 |
3940af1f627a4d49a2778803e87cb18c
|
|
| BLAKE2b-256 |
c34756ff0408ba078667862797d975b01a6173b35bd8861d5d2b80255c8bc3f6
|