python 数据库查询序列化_关于python:如何将SqlAlchemy结果序列化为JSON?

Django有一些从DB到JSON格式返回的ORM模型的自动序列化。

如何将SQLAlchemy查询结果序列化为JSON格式?

我尝试了jsonpickle.encode,但它对查询对象本身进行了编码。

我试过json.dumps(items)但它返回了

TypeError: is not JSON serializable

是否真的很难将SQLAlchemy ORM对象序列化为JSON / XML? 它没有默认的序列化器吗? 现在序列化ORM查询结果是非常常见的任务。

我需要的只是返回SQLAlchemy查询结果的JSON或XML数据表示。

需要在javascript datagird中使用SQLAlchemy对象的JSON / XML格式的查询结果(JQGrid http://www.trirand.com/blog/)

您可以将对象输出为dict:

class User:

def as_dict(self):

return {c.name: getattr(self, c.name) for c in self.__table__.columns}

然后使用User.as_dict()来序列化您的对象。

如将sqlalchemy行对象转换为python dict中所述

@charlax,我如何修复DateTime?通过使用这个我得到'datetime.datetime(2013,3,22,16,50,11)不是JSON序列化'当我做json.dumps

这是JSONEncoder对象的责任。您可以将其子类化为某个对象定义自己的编码器,包括datetime。请注意,Flask例如支持在JSON中开箱即用(使用最新版本)编码日期时间。

如果您使用sqlalchemy的"声明"方法,您可以将这样的内容添加到自定义Base类 - 这非常方便,因为您可以在任何ORM对象上调用my_orm_object.toDict()。类似地,您可以定义.toJSON()方法,该方法使用toDict方法和自定义编码器来处理日期,blob等

如何处理急切加载的关系?

我会避免倾销关系,并依赖客户端连接。如果你绝对想要包含关系,你可以有一个明确的列表,并在它们上面调用as_dict,或者你可以想象使用operator.attrgetter并明确所有内容。还有一种方法可以以编程方式在模型上建立关系。

还支持日期时间:return {c.name: unicode(getattr(self, c.name)) for c in self.__table__.columns}

无需修改自己的as_dict()转换,结果集中的行具有内部dict方法。试试这个:``import json rs = YourModel.query.all()s = json.dumps([r .__ dict__ for r in rs],default = alchemyencoder)print"result:"+ s``

如果您的类变量与列名称不同,则此方法无效。不知道如何获取类名吗?

但是如何编写解串器或这个模型呢?我是否必须为每个Column类编写代码?

@JamesBurke - 在这里查看(我的)答案的"更难的案例"部分。但是,像:{a.key: rowproxy[a.class_attribute.name] for a in User.__mapper__.attrs}

平面实施

你可以使用这样的东西:

from sqlalchemy.ext.declarative import DeclarativeMeta

class AlchemyEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj.__class__, DeclarativeMeta):

# an SQLAlchemy class

fields = {}

for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:

data = obj.__getattribute__(field)

try:

json.dumps(data) # this will fail on non-encodable values, like other classes

fields[field] = data

except TypeError:

fields[field] = None

# a json-encodable dict

return fields

return json.JSONEncoder.default(self, obj)

然后使用以下命令转换为JSON:

c = YourAlchemyClass()

print json.dumps(c, cls=AlchemyEncoder)

它将忽略不可编码的字段(将它们设置为"无")。

它不会自动扩展关系(因为这可能会导致自我引用,并永远循环)。

递归的,非循环的实现

但是,如果你宁愿循环,你可以使用:

from sqlalchemy.ext.declarative import DeclarativeMeta

def new_alchemy_encoder():

_visited_objs = []

class AlchemyEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj.__class__, DeclarativeMeta):

# don't re-visit self

if obj in _visited_objs:

return None

_visited_objs.append(obj)

# an SQLAlchemy class

fields = {}

for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:

fields[field] = obj.__getattribute__(field)

# a json-encodable dict

return fields

return json.JSONEncoder.default(self, obj)

return AlchemyEncoder

然后使用以下方法编码对象

print json.dumps(e, cls=new_alchemy_encoder(), check_circular=False)

这将编码所有孩子,他们所有的孩子,以及他们所有的孩子...基本上可能编码整个数据库。当它达到之前编码的内容时,它会将其编码为"无"。

递归的,可能循环的选择性实现

另一种可能更好的替代方法是能够指定要扩展的字段:

def new_alchemy_encoder(revisit_self = False, fields_to_expand = []):

_visited_objs = []

class AlchemyEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj.__class__, DeclarativeMeta):

# don't re-visit self

if revisit_self:

if obj in _visited_objs:

return None

_visited_objs.append(obj)

# go through each field in this SQLalchemy class

fields = {}

for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:

val = obj.__getattribute__(field)

# is this field another SQLalchemy object, or a list of SQLalchemy objects?

if isinstance(val.__class__, DeclarativeMeta) or (isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):

# unless we're expanding this field, stop here

if field not in fields_to_expand:

# not expanding this field: set it to None and continue

fields[field] = None

continue

fields[field] = val

# a json-encodable dict

return fields

return json.JSONEncoder.default(self, obj)

return AlchemyEncoder

你可能感兴趣的:(python,数据库查询序列化)