Skip to main content

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-trippingdatetime, date, time, and timedelta values survive save/load cycles as their Python types
  • Atomic writes — uses a temp file + os.replace so 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

Not thread-safe or process-safe. Concurrent writes from multiple threads or processes can 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

json_backed_dict-1.0.0.tar.gz (85.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

json_backed_dict-1.0.0-py3-none-any.whl (8.3 kB view details)

Uploaded Python 3

File details

Details for the file json_backed_dict-1.0.0.tar.gz.

File metadata

  • Download URL: json_backed_dict-1.0.0.tar.gz
  • Upload date:
  • Size: 85.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for json_backed_dict-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3d2102b7f3b0fdf8aba559e146eb06370d4ff3a84a0ddd3ad5439a165390e78a
MD5 fb03c038229610f76fdbf7c23f6e2196
BLAKE2b-256 a963594418e97c21b280baafeeec89da400eb86ab8eea4eea5eac9c1dbdefcd3

See more details on using hashes here.

Provenance

The following attestation bundles were made for json_backed_dict-1.0.0.tar.gz:

Publisher: publish.yml on skullydazed/json-backed-dict

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file json_backed_dict-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for json_backed_dict-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3f95522b599fc9fffdc80ae184819874faeeb1434d033f04dad5c4dca9919d6a
MD5 6f61129a3fc526217257a70ecb61ce4f
BLAKE2b-256 9a2999bea6ce52780926e81c04b4da38fae57a1cd68f90b31b550e19ea9cbf72

See more details on using hashes here.

Provenance

The following attestation bundles were made for json_backed_dict-1.0.0-py3-none-any.whl:

Publisher: publish.yml on skullydazed/json-backed-dict

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page