json-backed-dict
A dict subclass that automatically persists every mutation to a JSON file.
from json_backed_dict import JsonBackedDict as JBD
d = JBD('config.json')
d['host'] = 'localhost' # written to disk immediately
d['port'] = 5432 # written to disk immediately
Features
- Automatic persistence — every
__setitem__,__delitem__,update,pop, etc. atomically writes the file - Nested mutation tracking — mutating a nested dict or list is also persisted
- Temporal type round-tripping —
datetime,date,time, andtimedeltavalues survive save/load cycles as their Python types - Atomic writes — uses a temp file +
os.replaceso a crash mid-write never corrupts the file - Fast — backed by orjson for serialization
Installation
pip install json-backed-dict
Requires Python 3.9+.
Usage
Basic operations
from json_backed_dict import JsonBackedDict as JBD
d = JBD('data.json')
d['name'] = 'Alice'
d['scores'] = [10, 20, 30]
d.update({'active': True, 'level': 5})
print(d['name']) # 'Alice'
print(d.get('age')) # None
del d['level']
All standard dict methods work: keys(), values(), items(), pop(), setdefault(), popitem(), clear(), update().
Loading an existing file
If the file already exists, it is loaded on construction. The initial argument is ignored when a file is present.
d = JBD('data.json') # loads existing file
d = JBD('data.json', initial={'x': 1}) # initial ignored, file loaded
Seeding a new file
d = JBD('settings.json', initial={'debug': False, 'timeout': 30})
initial is only used when creating a new file.
Nested mutations
Nested dicts and lists returned by __getitem__ and get() are proxy objects. Mutating them persists the change to the root file automatically.
d = JBD('data.json', initial={'config': {'timeout': 10}, 'tags': ['a', 'b']})
d['config']['timeout'] = 30 # persisted
d['tags'].append('c') # persisted
d['config'].update({'retries': 3}) # persisted
Temporal types
datetime, date, time, and timedelta values are serialized to strings and deserialized back to their Python types on load. No manual conversion needed.
from datetime import datetime, date, time, timedelta
d = JBD('data.json')
d['created_at'] = datetime(2024, 6, 15, 10, 30, 45)
d['due_date'] = date(2024, 7, 1)
d['start_time'] = time(9, 0)
d['ttl'] = timedelta(hours=24)
d2 = JBD('data.json')
isinstance(d2['created_at'], datetime) # True
isinstance(d2['ttl'], timedelta) # True
Note: This means strings that look like dates, times, or timedeltas cannot be stored as plain strings — they will be coerced to the corresponding Python type on the next load. For example, storing "2024-01-15" will be read back as date(2024, 1, 15).
Supported value types
| Type | Example |
|---|---|
str |
'hello' |
int |
42 |
float |
3.14 |
bool |
True |
None |
None |
list |
[1, 2, 3] |
dict |
{'key': 'value'} |
datetime |
datetime(2024, 1, 1, 12, 0) |
date |
date(2024, 1, 1) |
time |
time(12, 0, 0) |
timedelta |
timedelta(days=1, hours=2) |
All dict keys must be str. Attempting to store any other type raises TypeError before any mutation occurs.
Limitations
Thread-safe, but not process-safe. Methods implemented by JsonBackedDict acquire an instance-level lock for their full duration, making individual operations on a single instance atomic. Concurrent writes from multiple processes can still interleave: each write creates a temp file and calls os.replace, so the last writer wins and earlier changes are silently lost.
Not an IPC mechanism. If another process modifies the backing file, the current instance will never see those changes. To pick up external changes, construct a new JBD from the same path.
License
MIT
Metadata
Release files for json-backed-dict 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| json_backed_dict-1.0.2.tar.gz | 89.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| json_backed_dict-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 99.7 kB
Release files / json_backed_dict-1.0.2.tar.gz
| Download URL | json_backed_dict-1.0.2.tar.gz |
|---|---|
| Size | 89.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b3e3def6c3c20abdf7bb181ff89f6a0b76e714d11c0b848a33590d45d2357fcc
|
|
BLAKE2b-256 checksum How to use checksums |
3b18678a555aa29fe6240d5cddaa6534d022fb8544cb2eb93089e8e1b0f90d29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 19, 2026.
Transparency logRelease files / json_backed_dict-1.0.2-py3-none-any.whl
| Download URL | json_backed_dict-1.0.2-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7dbf64a05334ae61ed83b95e0c788eebe36e2ecb9df7fdf5735c4511f718f151
|
|
BLAKE2b-256 checksum How to use checksums |
e4bf083ec960f29e194389d937b48dbc12313dce03e9550aded5efd4bb2d5218
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 19, 2026.
Transparency log