使用原始SQL时,在SQLAlchemy中反序列化JSON

时间:2017-11-02 19:57:59

标签: sqlalchemy

我有一个存储在文本列中的JSON表:

import json
from sqlalchemy import create_engine, Column, text, Integer, TEXT, TypeDecorator
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///:memory:')
engine.execute("create table t (t_id int not null primary key, attrs text not null)")
engine.execute("insert into t values (1, '{\"a\": 1, \"b\": 2}')")

Session = sessionmaker(bind=engine)

我使用SQLAlchemy文档中“Marshal JSON Strings”下定义的自定义类型在SQLAlchemy中定义了此表的映射:

Base = declarative_base()

# http://docs.sqlalchemy.org/en/rel_1_1/core/custom_types.html#marshal-json-strings
class JSONEncodedDict(TypeDecorator):
    impl = TEXT

    def process_bind_param(self, value, dialect):
        if value is not None:
            value = json.dumps(value)
        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            value = json.loads(value)
        return value

class T(Base):
    __tablename__ = 't'

    t_id = Column(Integer, primary_key=True)
    attrs = Column(JSONEncodedDict)

如果我查询所有T,则{J}对attrs进行反序列化:

session = Session()
t = session.query(T).first()
assert type(t.attrs) == dict, repr(t.attrs)

但是如果我使用文本查询/原始SQL,则不会反序列化:

session = Session()
t = session.query(T).from_statement(text('select * from t')).first()
assert type(t.attrs) == dict, repr(t.attrs)  # AssertionError: u'{"a": 1, "b": 2}'

在使用原始SQL查询时,如何使SQLAlchemy反序列化attrs列?

行为与其他数据库(MySQL,Postgres)相同。我正在使用的数据库(MySQL 5.5)不支持本机JSON类型,因此不能选择更改列类型。

1 个答案:

答案 0 :(得分:1)

您可以使用.columns()告诉TextClausetext())列类型:

from sqlalchemy import inspect

session = Session()
stmt = text('select * from t').columns(*inspect(T).columns)
t = session.query(T).from_statement(stmt).first()
assert type(t.attrs) == dict, repr(t.attrs)

或者,对于SQLAlchemy< 0.9,请使用typemap参数:

from sqlalchemy import inspect

session = Session()
typemap = {c.name: c.type for c in inspect(T).columns}
stmt = text('select * from t', typemap=typemap)
t = session.query(T).from_statement(stmt).first()
assert type(t.attrs) == dict, repr(t.attrs)