Skip to content

Instantly share code, notes, and snippets.

@kodekracker
Last active November 20, 2018 12:36
Show Gist options
  • Save kodekracker/b44dea8df6c0c90fdcdb to your computer and use it in GitHub Desktop.
Save kodekracker/b44dea8df6c0c90fdcdb to your computer and use it in GitHub Desktop.
A Custom SqlAlchemy JSON encoder class to encode models instances in json format which supports major object instances useful in developing api's in flask.
# To use this custom JsonEncoder class, you have to create a __json__() named
# function in each sqlalchemy model class, which basically return a list of model
# class attributes to be parsed, otherwise all attributes are processed present
# in `dir(class_name)`.
#
# Model Example:
# class User(db.Model):
# id = db.Column(db.Integer, primary_key=True)
# name = db.Column(db.String(100))
# email = db.Column(db.String(100))
#
# def __init__(self, name, email):
# self.name = name
# self.email = email
#
# def __json__(self):
# return ['name', 'email']
#
#
# And, also add this custom json encoder class (i.e AlchemyJsonEncoder) in your
# flask application instance (i.e app)
#
# app = Flask(__name__)
# app.json_encoder = AlchemyJSONEncoder
#
# Note:: This json encoder class supports various objects
# 1) Datetime
# 2) UUID
# 3) date
# 4) Decimal (returned by SqlAlchemy db.Numeric class)
# 5) Markup
#
from sqlalchemy.ext.declarative import DeclarativeMeta
from flask import json
from decimal import Decimal
from datetime import date
class AlchemyJSONEncoder(json.JSONEncoder):
def default(self, o):
# check if object `o` is of custom declared model instance
if isinstance(o.__class__, DeclarativeMeta):
data = {}
fields = o.__json__() if hasattr(o, '__json__') else dir(o)
for field in [f for f in fields if not f.startswith('_') and
f not in ['metadata', 'query', 'query_class']]:
value = o.__getattribute__(field)
try:
if json.dumps(value):
data[field] = value
except TypeError:
data[field] = None
return data
# check if object `o` is of Decimal instance
elif isinstance(o, Decimal):
return o.to_eng_string()
# check if object `o` is of date instance
elif isinstance(o, date):
return o.isoformat()
# rest of objects are handled by default JSONEncoder like 'Datetime',
# 'UUID', 'Markdown' and various others
return json.JSONEncoder.default(self, o)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment