10

I have a sqlalchemy result

labels = session.query(
         LabelsData, 
         LabelsData.id, 
         LabelsData.name, 
         LabelsData.color
         ).filter(LabelsData.deleted==False).all()

And I want convert this result to JSON, but how I can do it?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Nolik
  • 4,337
  • 5
  • 18
  • 14

6 Answers6

20

It looks like your LabelsData object is a SQLAlchemy model. You need to serialize it before dumping it to JSON. Here's a short example that extracts all the columns from your LabelsData object and converts the results of your query to JSON:

from json import dumps
from sqlalchemy.orm import class_mapper

def serialize(model):
  """Transforms a model into a dictionary which can be dumped to JSON."""
  # first we get the names of all the columns on your model
  columns = [c.key for c in class_mapper(model.__class__).columns]
  # then we return their values in a dict
  return dict((c, getattr(model, c)) for c in columns)

# we can then use this for your particular example
serialized_labels = [
  serialize(label)
  for label in session.query(LabelsData).filter(LabelsData.deleted == False)
]
your_json = dumps(serialized_labels)
mgilson
  • 300,191
  • 65
  • 633
  • 696
mtth
  • 4,671
  • 3
  • 30
  • 36
2
from collections import OrderedDict

class DictSerializable(object):
    def _asdict(self):
        result = OrderedDict()
        for key in self.__mapper__.c.keys():
            result[key] = getattr(self, key)
        return result

From here and appearing to require simplejson. Hope that helps...

UPDATE: on a second look, it's a dictionary, which you can dump by any of the json modules in python.

hd1
  • 33,938
  • 5
  • 80
  • 91
  • Need to handle datetime values that can not be serialized directly .. using something like given below :: def handler(o): if hasattr(o, 'isoformat') and callable(o.isoformat): return o.isoformat() raise TypeError("Can't serialize %r" % (o,)) jsonize = lambda d: json.dumps(d, default=_handler) courstey 'Thomas Dignan' at [link](http://piotr.banaszkiewicz.org/blog/2012/06/30/serialize-sqlalchemy-results-into-json/) – saurshaz Sep 05 '13 at 04:47
1

Looks like sqlalchemy already has one http://docs.sqlalchemy.org/en/latest/core/serializer.html

from sqlalchemy.ext.serializer import loads, dumps
metadata = MetaData(bind=some_engine)
Session = scoped_session(sessionmaker())

# ... define mappers

query = Session.query(MyClass).filter(MyClass.somedata=='foo').order_by(MyClass.sortkey)

# pickle the query
serialized = dumps(query)

# unpickle.  Pass in metadata + scoped_session
query2 = loads(serialized, metadata, Session)

print query2.all()
Nande
  • 409
  • 1
  • 6
  • 11
  • 1
    This seems to apply only to the query itself, not the data contained therein. I think the OP is asking about encoding the results of a query object as json. – Peter Grace Mar 21 '14 at 21:09
  • Beware, with SQLAlchemy 2.0, The serializer extension is legacy and should not be used for new development. – LeMoussel Apr 18 '23 at 13:00
1

This blog post provided the solution I went with: http://blogs.gnome.org/danni/2013/03/07/generating-json-from-sqlalchemy-objects/

The strategy used was to include a .todict method directly to a Base mixin which iterates over the parent class's sqlalchemy columns.

Alternatively, Nande's approach (https://stackoverflow.com/a/19602809/837575) to use sqlalchemy.ext.serializer works well if you're trying to serialize data over the wire but don't necessarily need it as json.

Community
  • 1
  • 1
mekarpeles
  • 365
  • 3
  • 9
0

I add this anwser as it is a mix of @mekarpeles and @hd1. I mean I did not modified the sqlalchemy hierarchy of objects, just delegating to a simple JSONEncoder:

# given that you have 
Base = declarative_base()

class SqlAlchemyModelEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Base):
            result = OrderedDict()
            for key in obj.__mapper__.c.keys():
                result[key] = getattr(obj, key)
            return result
        return json.JSONEncoder.default(self, obj)

If your models use not serializable classes (datetime for example) you have to add them to the Encoder :

if isinstance(obj, datetime):
    return obj.isoformat()

And then I use it with a jinja2 context filter :

@contextfilter
def tojson(ctx, model, *elements, **kw):
    return json.dumps(model, cls=SqlAlchemyModelEncoder)
Bruno Thomas
  • 1,179
  • 17
  • 31
0

https://github.com/TaylorHere/PythonSerializer
the link above can give you a hand , It's a small script that can simply serialize sql query result to list or dict ,just like this:

#Useage with flask and SQLalchemy
from serializer import serializer
def my_location():
    if request.method == 'GET':
        user = db_session.query(User).filter(
        User.openid == session['user_id']).first()
        addresses = user.addresses
        return jsonify({'data': serializer(addresses.instance, 'sqlalchemy')})
Taylor
  • 1