A dict subclass that automatically persists every mutation to a JSON file
Project description
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
Project details
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 json_backed_dict-1.0.1.tar.gz.
File metadata
- Download URL: json_backed_dict-1.0.1.tar.gz
- Upload date:
- Size: 86.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ddf4f0b9e5cc21f55df930e838d8b40224ba5331c8d297b92c0cd9353cc148a
|
|
| MD5 |
a2c01728e9485a63a2cceb95d1580071
|
|
| BLAKE2b-256 |
45c6a604fae2b7b11bfc9c2f22f0ebc7d21c457149f32fa6988a0df2b54c94ee
|
Provenance
The following attestation bundles were made for json_backed_dict-1.0.1.tar.gz:
Publisher:
publish.yml on skullydazed/json-backed-dict
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
json_backed_dict-1.0.1.tar.gz -
Subject digest:
3ddf4f0b9e5cc21f55df930e838d8b40224ba5331c8d297b92c0cd9353cc148a - Sigstore transparency entry: 1202577645
- Sigstore integration time:
-
Permalink:
skullydazed/json-backed-dict@b650348155b5c4b9ea781b31c34e0676b1d7cd58 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/skullydazed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b650348155b5c4b9ea781b31c34e0676b1d7cd58 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file json_backed_dict-1.0.1-py3-none-any.whl.
File metadata
- Download URL: json_backed_dict-1.0.1-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9186603ccdd904f5e3704ba15cd0a78c37f3f7be7a44a483969f65ee3a4157c4
|
|
| MD5 |
a8d8656eaec673887db404b9a32eb384
|
|
| BLAKE2b-256 |
7f1cedcd6c4800df7fa589f4cc619f02f60c6bf0e7948dc7092e921706221abe
|
Provenance
The following attestation bundles were made for json_backed_dict-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on skullydazed/json-backed-dict
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
json_backed_dict-1.0.1-py3-none-any.whl -
Subject digest:
9186603ccdd904f5e3704ba15cd0a78c37f3f7be7a44a483969f65ee3a4157c4 - Sigstore transparency entry: 1202577661
- Sigstore integration time:
-
Permalink:
skullydazed/json-backed-dict@b650348155b5c4b9ea781b31c34e0676b1d7cd58 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/skullydazed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b650348155b5c4b9ea781b31c34e0676b1d7cd58 -
Trigger Event:
workflow_dispatch
-
Statement type: