为Flask-Restless API序列化Python Arrow对象

时间:2015-01-05 01:52:43

标签: python json serialization flask-restless

我目前正在使用Flask-Restless开发一个应用程序。当我替换我的SQLAlchemy模型'典型的DateTime字段以及相应的arrow字段,一切顺利。这是由于SQLAlchemy-Utils及其ArrowType字段的帮助。

但是,在使用API​​返回这些对象的JSON表示后,我收到以下错误:

TypeError:箭头[2015-01-05T01:17:48.074707]不是JSON可序列化的

修改模型序列化方式的理想位置在哪里?我是否修改了Flask-Restless代码以支持Arrow对象或编写Flask-Restless可以识别并用于检索JSON兼容对象的模型方法?

我也可以在此期间编写一个丑陋的后处理器功能,但这个解决方案看起来像是一个可怕的黑客。

下面是一个带有ArrowType字段的示例模型:

class Novel(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.Unicode, unique=True, nullable=False)
    created_at = db.Column(ArrowType, nullable=False)

    def __init__(self, title):
        self.title = title
        self.created_at = arrow.utcnow()

2 个答案:

答案 0 :(得分:4)

箭头现在有一个for_json方法。例如:arrow.utcnow().for_json()

答案 1 :(得分:3)

支持箭头类型的自定义JSONEncoder怎么样?查看Flask-Restless源代码,它使用Flask内置的jsonify。有关以不同格式序列化常规datetime个对象的示例,请参阅此代码段:http://flask.pocoo.org/snippets/119/

以下是一个完整的自包含示例:

import flask
import flask.ext.sqlalchemy
import flask.ext.restless
from flask.json import JSONEncoder
import sqlalchemy_utils
import arrow

app = flask.Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = flask.ext.sqlalchemy.SQLAlchemy(app)

class Event(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    timestamp = db.Column(sqlalchemy_utils.ArrowType)

class ArrowJSONEncoder(JSONEncoder):
    def default(self, obj):
        try:
            if isinstance(obj, arrow.Arrow):
                return obj.format('YYYY-MM-DD HH:mm:ss ZZ')
            iterable = iter(obj)
        except TypeError:
            pass
        else:
            return list(iterable)
        return JSONEncoder.default(self, obj)

app.json_encoder = ArrowJSONEncoder

db.create_all()
manager = flask.ext.restless.APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(Event, methods=['GET','POST'])

app.run()

从帖子中的两个选项中,我建议将方法添加到模型类中以检索与JSON兼容的对象,这只是因为它更简单,更易于维护。如果你想修改Flask-Restless,你需要对它进行分叉或修补它。