Simple “object-db” using JSON and python-sqlite
Posted: December 5, 2008 Filed under: json, modules, programming, Python | Tags: centos, oodb, python-sqlite2, rpm, sqlite 1 Comment »As part of a much larger project, I have a group of “snapshots” of a complicated data structure. I need to save these in a persistent way, and continue to have access to them, when needed. My solution is to output the snapshots as JSON, and store them into a sqlite database*, where they will be persistent on disk as “jlobs” (json large objects).
This “sqlite as object-db“ has several advantages:
- atomic transactions,
- easy database replication,
- jlob can easily change format without affecting schema
- very light runtime requirements.
Building off of the sqlite3 manual, it is easy to see how to extract the json back *out* of the database.
There are drawbacks to this approach, of course:
- you’re responsible for building and maintaining tables indexing any queryable elements of your jlob, if you want to be able to access them using SQL.
- sql normalization purists will throw up when they look at your schema
(*Note: if you are on centos 5, and do not have access to Python 2.5, make sure that you install python-sqlite2, for example from one of these rpms) rather than updating your python-sqlite in place. BAD THINGS WILL HAPPEN, including breaking yum. )
#!/usr/bin/python
import sys
if sys.version_info >= (2,5):
import sqlite3
else:
from pysqlite2 import dbapi2 as sqlite3
try:
import json
except ImportError:
import simplejson as json
sqlite3.register_converter("json", json.loads)
conn = sqlite3.connect(":memory:", \
detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
c = conn.cursor()
c.row_factory = sqlite3.Row # fields by name
d = conn.cursor() # normal row
json_string = json.dumps( dict(a=1,b=[1,2,3]))
conn.execute('''
create table snapshot(
id INTEGER PRIMARY KEY AUTOINCREMENT,
mydata json);
''')
conn.execute('''
insert into snapshot values
(null, ?)''', (json_string,))
R1 = c.execute("select * from snapshot").fetchone()['mydata']
R2 = d.execute("select * from snapshot").fetchone()[1]
R3 = conn.execute("select * from snapshot").fetchone()[1]
assert R1==R2==R3 == {'a': 1, 'b': [1, 2, 3]}, "all should be equal"
hi Gregg, here’s an update which might be helpful for your project requiring serialization + persistance via Python for SQLite: y_serial module at http://yserial.sourceforge.net — compression and regex were also added
Go schema-less !