Skip to content

Instantly share code, notes, and snippets.

@sloat
Created August 31, 2013 16:07
Show Gist options
  • Save sloat/6399164 to your computer and use it in GitHub Desktop.
Save sloat/6399164 to your computer and use it in GitHub Desktop.
JSON encoder for SQLAlchemy models, using the inspection API. Not thoroughly tested. No warranty, blah blah. Improvements welcomed!
import json
from sqlalchemy.inspection import inspect
class AlchemyEncoder(json.JSONEncoder):
'''JSON encoder for SQLAlchemy models, using inspection API'''
def __init__(self, skipkeys=False, ensure_ascii=True,
check_circular=True, allow_nan=True, sort_keys=False,
indent=None, separators=None, default=None, relations=False,
**kw):
self._include_relations = relations
super(AlchemyEncoder, self).__init__(
skipkeys=False,
ensure_ascii=True,
check_circular=True,
allow_nan=True,
indent=None,
separators=None,
default=None,
**kw
)
def default(self, obj):
'''
inspect columns of sqlalchemy model, create secondary encoder if
necessary for relationships and make it so we don't go more than one
level deep.
'''
info = inspect(obj)
if not info.is_instance:
raise TypeError('%s is not an instance' % obj)
output = {}
cols = info.mapper.columns
for colname in cols.keys():
if colname in info.dict:
output[colname] = info.dict[colname]
else:
output[colname] = None
if self._include_relations:
encoder = AlchemyEncoder(relations=False)
for relname, relinfo in info.mapper.relationships.items():
if relname in info.dict:
if relinfo.uselist:
output[relname] = []
for relobj in info.dict[relname]:
if relobj == obj:
output[relname].append({'self': True})
else:
output[relname].append(encoder.default(relobj))
else:
output[relname] = encoder.default(relobj)
return output
def model_json(obj, relations=False):
return json.dumps(obj, cls=AlchemyEncoder, relations=relations)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment