Pure Python decoder for Clojure Nippy-encoded data
Project description
nippy-decoder
pure python decoder for clojure nippy serialized data.
zero dependencies. uses only python standard library.
- what and why
- installation
- how to use
- type mapping
- what's supported
- what's not
- examples
- development
- license
what and why
nippy is clojure's fast serialization format. if you have clojure/java services storing data as nippy-encoded bytes (in postgres, redis, kafka, etc.), you need a way to decode it in python.
this decoder:
- reads nippy bytes into python dicts, lists, strings, etc.
- has zero dependencies (just stdlib)
- is simple: 200 lines of code
- is validated against official clojure
taoensso/nippy
installation
pip install nippy-decoder
how to use
basic decoding
from nippy_decoder import NippyDecoder
decoder = NippyDecoder()
# from anywhere: database, file, api, kafka...
nippy_bytes = b'NPY\x00...'
result = decoder.decode(nippy_bytes)
# => {'name': 'alice', 'age': 30, 'active': True}
from database
postgres with psycopg2:
import psycopg2
from nippy_decoder import NippyDecoder
decoder = NippyDecoder()
conn = psycopg2.connect("dbname=mydb")
cur = conn.cursor()
# query nippy-encoded column
cur.execute("""
SELECT id, data
FROM facts
WHERE created_at > %s
""", (since_date,))
for fact_id, nippy_bytes in cur:
decoded = decoder.decode(nippy_bytes)
print(f"{fact_id}: {decoded}")
sqlite:
import sqlite3
from nippy_decoder import NippyDecoder
decoder = NippyDecoder()
conn = sqlite3.connect('/path/to/db.sqlite')
cur = conn.cursor()
cur.execute("SELECT id, nippy_data FROM records")
for row_id, nippy_bytes in cur:
decoded = decoder.decode(nippy_bytes)
# work with python dict/list/etc
from api response
import requests
from nippy_decoder import NippyDecoder
decoder = NippyDecoder()
response = requests.get("https://api.example.com/facts/123")
decoded = decoder.decode(response.content)
print(decoded['status']) # => 'active'
error handling
from nippy_decoder import NippyDecoder
decoder = NippyDecoder()
try:
result = decoder.decode(data)
except ValueError as e:
print(f"decode failed: {e}")
# "invalid nippy header"
# "unsupported nippy version: 5"
# "unsupported type: 200"
type mapping
| clojure | python | example |
|---|---|---|
nil |
None |
|
true / false |
True / False |
|
| integer | int |
42 → 42 |
| float / double | float |
3.14 → 3.14 |
| string | str |
"hello" → "hello" |
| keyword | str |
:status → "status" |
| vector | list |
[1 2 3] → [1, 2, 3] |
| map | dict |
{:a 1 :b 2} → {"a": 1, "b": 2} |
| set | set |
#{1 2 3} → {1, 2, 3} |
| uuid | str |
uuid → "550e8400-..." |
| bytes | bytes or dict |
auto-parses json if detected |
note on keywords: clojure keywords like :status become python strings "status" (without the :).
note on byte arrays: if a byte array starts with { or [, the decoder attempts to parse it as json and returns a dict/list. otherwise returns raw bytes.
what's supported
- primitives: null, boolean, integers (8-64 bit), floats, doubles
- strings: utf-8 strings with 1-4 byte length prefixes (types 11-14, 105)
- keywords: clojure keywords (types 33-35, 106)
- collections: vectors (types 19-23), maps (types 24-26, 112), sets (types 27-29), lists (types 30-32)
- binary: byte arrays (types 15-18), uuids (type 36)
- metadata: type 37 (skipped, value returned)
- extended: legacy collection types (44-127)
validated against nippy version 0 (standard format since 2014).
what's not
- encoding - this is decode-only
- nippy v1+ - only v0 supported (but v0 is the standard)
- custom types - custom nippy extensions not supported
- types > 127 - reserved/future types not implemented
if you need encoding, use the official taoensso/nippy in clojure.
examples
decode primitives:
decoder = NippyDecoder()
# integer
decoder.decode(b'NPY\x00\x07\x00\x00\x00\x2a') # => 42
# string
decoder.decode(b'NPY\x00\x0c\x05hello') # => "hello"
# keyword
decoder.decode(b'NPY\x00\x21\x06status') # => "status"
decode collections:
# vector
decoder.decode(b'NPY\x00\x15\x03...') # => [1, 2, 3]
# map
result = decoder.decode(b'NPY\x00\x18\x02...')
# => {"name": "test", "age": 25}
# nested
result = decoder.decode(b'NPY\x00\x18\x01...')
# => {"user": {"name": "alice", "active": True}}
decode uuid:
result = decoder.decode(b'NPY\x00\x24...')
# => "ba8feab4-9efb-4635-97d2-be648a141fb4"
complex nested data:
# decode nested maps with multiple data types
fact_bytes = get_from_database(record_id)
record = decoder.decode(fact_bytes)
print(record)
# {
# 'record-id': 'ba8feab4-9efb-4635-97d2-be648a141fb4',
# 'status': 'PENDING',
# 'priority': 1,
# 'metadata': {
# 'contribution': 179.03,
# 'interest': 50.25
# }
# }
development
# clone
git clone https://github.com/HariprasathSankaraiyan/nippy-decoder
cd nippy-decoder
# install in dev mode
pip install -e .
# run examples
python examples/basic_usage.py
# run tests (requires pytest)
pip install pytest
pytest tests/ -v
structure:
nippy-decoder/
├── src/nippy_decoder/
│ ├── decoder.py # core logic
│ └── __init__.py
├── tests/ # pytest suite
│ ├── test_primitives.py
│ ├── test_collections.py
│ └── test_uuid.py
├── examples/
│ └── basic_usage.py # usage examples
├── pyproject.toml # package metadata
├── README.md
└── LICENSE
license
MIT License
Copyright © 2025 nippy-decoder contributors
issues and prs welcome!
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 nippy_decoder-0.1.0.tar.gz.
File metadata
- Download URL: nippy_decoder-0.1.0.tar.gz
- Upload date:
- Size: 262.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86d0c9ac60e3b9303956e9b57dc11c8a35fe2a5caf5bdd9143f65327a6c6f365
|
|
| MD5 |
7faf545766fbb43bc75392dc8ec1a946
|
|
| BLAKE2b-256 |
08e5a107aa38bc14837fae232fb5ff3d93f1007ffbe098464b829c9e6245cf45
|
File details
Details for the file nippy_decoder-0.1.0-py3-none-any.whl.
File metadata
- Download URL: nippy_decoder-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7528ccb61bed7ce5764223173edf7a9adae8689e04b0adcc682ef58b71b37aa8
|
|
| MD5 |
d0adb6c837d0eb2dbd49ec97e3bbe520
|
|
| BLAKE2b-256 |
1756a8e2d3fed7d9604c4ea3dfdffd65fcf738ed5c7cc9dbff2542cf4caaf981
|