dynojson
Marshall / unmarshall JSON to and from DynamoDB JSON format — a fast Python library backed by Rust.
Convert between regular JSON and DynamoDB JSON format on the terminal or in your Python code. Powered by a Rust core via PyO3 for maximum performance.
- 🔥 Works on all platforms (Linux, macOS, Windows)
- 📄 Convert a file from a given file path
- ✏️ Convert a JSON string directly
- ⛓ Read from stdin — pipe in JSON from another command
- 🍰 Extract and convert only a subset of the JSON
- 🤝 Output can be piped or redirected to other commands
- 🧰 Integrate into your workflow with AWS DynamoDB CLI
Installation
Python API
All functions accept JSON strings or Python dicts/lists directly. The return type matches the input type.
# ── With dicts (recommended) ──────────────────────────────────────
=
# {"name": {"S": "Alice"}, "age": {"N": "30"}} ← returns a dict
=
# {"name": "Alice", "age": 30} ← returns a dict
# ── With strings (also supported) ─────────────────────────────────
=
# '{"name":{"S":"Alice"},"age":{"N":"30"}}' ← returns a string
=
# '{"name":"Alice","age":30}' ← returns a string
# ── Extract a property ────────────────────────────────────────────
=
=
# [{"type": "fruit"}]
File & Directory API
Process files and directories directly — Rust handles all I/O, skipping Python-Rust FFI overhead for large payloads.
# ── Single file ─────────────────────────────────────────────────
# File → dict (no output_path)
=
# File → file (with output_path)
# With property extraction
=
# ── Directory batch processing ──────────────────────────────────
# Mirror mode — one output file per input file
=
# Merge mode — all results into a single JSON array
=
# With property extraction (e.g. DynamoDB scan exports)
=
CLI Usage
)
Unmarshall (DynamoDB JSON → regular JSON)
# From a JSON string
}
# From a file
# From stdin
|
# From AWS CLI
|
Marshall (regular JSON → DynamoDB JSON)
# From a JSON string
}}}
# From a file
# From stdin
|
Extract a subset of JSON with -g
Use dot-notation to select a property. Supports numeric array indices and * to expand all array items.
# Get a specific property
# Expand all items
# With AWS CLI scan output
|
DynamoDB type mapping
| JSON type | DynamoDB descriptor |
|---|---|
| String | {"S": "…"} |
| Number | {"N": "…"} |
| Boolean | {"BOOL": …} |
| Null | {"NULL": true} |
| Array | {"L": […]} |
| Object | {"M": {…}} |
String sets (SS), number sets (NS), and binary types (B, BS) are also supported during unmarshalling.
Benchmarks
The dict path is faster than the string path because it skips two JSON serialization round-trips (json.dumps + json.loads on the Python side).
| Payload | Marshall speedup | Unmarshall speedup |
|---|---|---|
| Small (1 item) | 1.28x | 1.15x |
| Medium (100 items) | 1.20x | 1.22x |
| Large (10,000 items) | 1.14x | 1.22x |
Run the benchmark yourself:
Development
Prerequisites
Setup
# Clone the repo
# Create a virtual environment
# Install build and test dependencies
# Build and install in development mode
# Run Rust tests
# Run Python tests
Project structure
dynojson/
├── Cargo.toml # Rust package manifest
├── pyproject.toml # Python package manifest (maturin build)
├── README.md
├── LICENSE
├── CONTRIBUTING.md
├── src/
│ ├── lib.rs # PyO3 module + re-exports
│ ├── error.rs # Custom error types (thiserror)
│ ├── marshall.rs # Regular JSON → DynamoDB JSON
│ ├── unmarshall.rs # DynamoDB JSON → regular JSON
│ └── property.rs # Dot-path property extraction
├── python/
│ └── dynojson/
│ ├── __init__.py # Public Python API
│ ├── _dynojson.pyi # Type stubs
│ └── cli.py # CLI entry point
├── benchmarks/
│ └── bench_marshall.py # String vs dict path benchmark
└── tests/
├── test_marshall.py
├── test_unmarshall.py
├── test_property.py
├── test_file_io.py
└── test_cli.py
Acknowledgements
This project was inspired by ddbjson by Alexandre Duarte, an excellent Node.js CLI tool for converting DynamoDB JSON. dynojson is a ground-up Rust rewrite with Python bindings, building on the same ideas.