Created
October 1, 2012 00:39
-
-
Save goodwillcoding/3808838 to your computer and use it in GitHub Desktop.
JSON Serializable SQLAlchemy Object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class JsonSerializableMixin(object): | |
def __json__(self, request): | |
""" | |
Converts all the properties of the object into a dict for use in json. | |
You can define the following in your class | |
_json_eager_load : | |
list of which child classes need to be eagerly loaded. This applies | |
to one-to-many relationships defined in SQLAlchemy classes. | |
_base_blacklist : | |
top level blacklist list of which properties not to include in JSON | |
_json_blacklist : | |
blacklist list of which properties not to include in JSON | |
:param request: Pyramid Request object | |
:type request: <Request> | |
:return: dictionary ready to be jsonified | |
:rtype: <dict> | |
""" | |
props = {} | |
# grab the json_eager_load set, if it exists | |
# use set for easy 'in' lookups | |
json_eager_load = set(getattr(self, '_json_eager_load', [])) | |
# now load the property if it exists | |
# (does this issue too many SQL statements?) | |
for prop in json_eager_load: | |
getattr(self, prop, None) | |
# we make a copy because the dict will change if the database | |
# is updated / flushed | |
options = self.__dict__.copy() | |
# setup the blacklist | |
# use set for easy 'in' lookups | |
blacklist = set(getattr(self, '_base_blacklist', [])) | |
# extend the base blacklist with the json blacklist | |
blacklist.update(set(getattr(self, '_json_blacklist', []))) | |
for key in options: | |
# skip blacklisted properties | |
if key in blacklist: | |
continue | |
# do not include private and SQLAlchemy properties | |
if not key.startswith('__') and not key.startswith('_sa_'): | |
obj = getattr(self, key) | |
# format and date/datetime/time properties to isoformat | |
if isinstance(obj, (datetime, date, time)): | |
props[key] = obj.isoformat() | |
else: | |
# get the class property value | |
attr = getattr(self, key) | |
# let see if we need to eagerly load it | |
if key in json_eager_load: | |
# this is for SQLAlchemy foreign key fields that | |
# indicate with one-to-many relationships | |
if not hasattr(attr, 'pk'): | |
if attr: | |
# jsonify all child objects | |
attr = [x.__json__(request) for x in attr] | |
else: | |
# convert all non integer strings to string or if | |
# string conversion is not possible, convert it to | |
# Unicode | |
if attr and not isinstance(attr, (int, float)): | |
try: | |
attr = str(attr) | |
except UnicodeEncodeError: | |
attr = unicode(attr) # .encode('utf-8') | |
props[key] = attr | |
return props |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment