arpeggio-shredder
Reversible shredding (flatten) and unshredding (rebuild) of semi-structured JSONL into Apache Arrow RecordBatches.
Source Code: https://codeberg.org/alwyna/shredder
This package provides a thin Python binding over a C++ core that converts JSON documents into a columnar “atoms” representation suitable for Arrow / Parquet workflows, while preserving the ability to reconstruct the original documents exactly.
The scope is intentionally narrow: flattening with reversibility, not general JSON processing.
Key properties
- Reversible: JSON → Arrow atoms → JSON
- Columnar-first: output is optimized for Arrow-native pipelines
- Deterministic identity: optional object and transaction tagging
- Minimal Python surface: High-level
shredderpackage or rawshredder_extextension
Installation
pip install arpeggio-shredder
Usage
Shredder 0.2.0 supports two explicit "codec" strategies: json (UTF-8 text) and arrow (native Struct/List DOM).
Known limitations / Non-goals for 0.2.x
- No support for array-of-array: Shredder throws a
runtime_erroron nested arrays (e.g.,[[1,2]]). - Row expansion semantics (no sibling back-fill): Fields encountered after an array may only be present in the last expanded row. Reconstruction remains correct via internal metadata.
- Depth/complexity caveat: The iterative core is frozen for 0.2.0. We prioritize stability over redesigning the traversal engine for extreme nesting.
- Codec strategy is explicit:
codec="json"requires strings;codec="arrow"requires Arrow DOM (struct/list). No auto-detection.
1. JSON Text Codec (Default)
Warning: The
jsoncodec expects UTF-8 JSON strings (e.g.,pa.string()), not Python dicts or Arrow structs. No silent casting is performed.
The classic workflow: JSONL → Arrow atoms → JSONL.
import pyarrow as pa
import shredder
# 1. Load JSONL as Arrow string array
lines = ['{"id": 1, "msg": "hello"}', '{"id": 2, "msg": "world"}']
array = pa.array(lines, type=pa.string())
# 2. Shred into columnar "atoms"
# codec="json" is default, but can be explicit
atoms = shredder.shred(array, codec="json")
# 3. Unshred back to JSON
# Returns RecordBatch with single column 'doc'
reconstructed = shredder.unshred(atoms, codec="json")
json_docs = reconstructed.column(0)
for doc in json_docs:
print(doc.as_py())
2. Arrow DOM Codec
New in 0.2.0: Treat Arrow nested structures as the source of truth. No JSON parsing involved.
import pyarrow as pa
import pyarrow.json as pajson
import shredder
# 1. Read JSONL into Arrow-native columns
# table = pajson.read_json("input.jsonl")
table = pa.table({"id": [1, 2], "val": [10.5, 20.0]})
# 2. Convert to a single struct column (Arrow DOM input)
doc_struct = pa.StructArray.from_arrays(table.columns, names=table.column_names)
# 3. Use the stateful Shredder class
s = shredder.Shredder(codec="arrow")
# 4. Shred/Unshred
atoms = s.shred(doc_struct)
reconstructed = s.unshred(atoms)
# Output 'doc' column is the reconstructed StructArray
doc_out = reconstructed.column(0)
print(doc_out.to_pylist())
How it works
- Codecs:
JsonTextCodec: 1-col UTF-8 string → internal DOM → atoms.ArrowDomCodec: 1-col Arrow struct/list/etc → internal DOM → atoms.
- Flattening: Nested objects are flattened into path-based columns (e.g.,
root_user_name). - Row Expansion: Nested arrays are "shredded" by duplicating parent values for each array element, adding an
__idxcolumn to preserve order. - Identity: The engine automatically injects
__obj_idand__txn_id(BLAKE3 hashes of content) to ensure perfect reconstruction. - Reversibility: Shredder preserves enough metadata to rebuild the exact original structure, regardless of the input codec.
Native extension
The package ships with a prebuilt native extension (.so) built against Apache Arrow and exposed via pybind11.
- No runtime compilation
- No system Arrow installation required
- Shared libraries are bundled into the wheel
Platform support
- OS: Linux (manylinux-compatible)
- Architecture: x86_64
- Python: CPython 3.12
- ABI: glibc (manylinux)
Other platforms are not currently supported.
Relationship to the C++ project
This package is the Python distribution layer for the Shredder C++ project hosted on Codeberg: https://codeberg.org/alwyna/shredder.
License
This package is dual-licensed:
- AGPL-3.0 for open-source use and networked deployments
- Commercial license for proprietary or closed-source use
Commercial licensing is available via https://arpeggio.one/shop.
Metadata
Release files for arpeggio-shredder 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| arpeggio_shredder-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.39+ x86-64 | Details for arpeggio_shredder-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl |
Release files / arpeggio_shredder-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl
| Download URL | arpeggio_shredder-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl |
|---|---|
| Size | 24.8 MB |
| Tags | CPython 3.12 Linux glibc 2.39+ x86-64 |
|
SHA-256 checksum How to use checksums |
dca31c8f7edaf707a1852cce7eddf4c20334f175c7f04e32ae498791fc07d226
|
|
BLAKE2b-256 checksum How to use checksums |
036642eab851045e2db5fb83e416ab887a06737b4f6d28095d58e91fc326bfd9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|
Security for arpeggio-shredder 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.