如何将SQLAlchemy转换为JSON

10
我有一个 sqlalchemy 的查询结果。
labels = session.query(
         LabelsData, 
         LabelsData.id, 
         LabelsData.name, 
         LabelsData.color
         ).filter(LabelsData.deleted==False).all()

我想将这个结果转换为JSON格式,但我该怎么做呢?

嗯,json - Burhan Khalid
2
可以,但是 sqlalchemy 的结果不能被编码为 JSON :( - Nolik
你可以使用我回答中的代码片段 https://dev59.com/E2w05IYBdhLWcg3wqzms#14322313 - n0nSmoker
6个回答

20

看起来你的LabelsData对象是一个SQLAlchemy模型。在将其转储为JSON之前,您需要对其进行序列化。以下是一个简短的示例,从您的LabelsData对象中提取所有列,并将查询结果转换为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)

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

以下内容翻译自这里,需要使用simplejson

更新:仔细看了一下,它其实是一个字典,你可以使用Python中的任何JSON模块进行转储。


需要处理无法直接进行序列化的日期时间值..使用以下方式如下::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) 由'Thomas Dignan'提供,来源于链接 - saurshaz

1

看起来SQLAlchemy已经有一个相关的文档了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()

1
这似乎仅适用于查询本身,而不适用其中包含的数据。我认为OP是在询问如何将查询对象的结果编码为json。 - Peter Grace
请注意,使用SQLAlchemy 2.0时,序列化扩展是遗留的,不应该用于新的开发。 - LeMoussel

1

链接的博客文章没有代码格式。只有黑白色块状文本。 - Zoran Pavlovic

0

我添加这个答案,因为它是@mekarpeles和@hd1的混合体。我的意思是,我没有修改sqlalchemy对象层次结构,只是委托给一个简单的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)

如果您的模型使用了不可序列化的类(例如datetime),则必须将它们添加到编码器中:
if isinstance(obj, datetime):
    return obj.isoformat()

然后我使用它与jinja2上下文过滤器:

@contextfilter
def tojson(ctx, model, *elements, **kw):
    return json.dumps(model, cls=SqlAlchemyModelEncoder)

0

https://github.com/TaylorHere/PythonSerializer
上面的链接可以帮助你,这是一个小脚本,可以将SQL查询结果简单地序列化为列表或字典,就像这样:

#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')})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接