TypeError:对象不可JSON序列化

时间:2019-06-25 05:09:13

标签: json serialization flask-sqlalchemy

我被以下错误所吸引:

TypeError: Object of type 'Menu' is not JSON serializable

毕竟,当我转到端点'/users'时,数据已经存在,并进行了序列化:

menu: [
   {
    id: 1,
    created: "2019-06-24T22:24:50.811520",
    items: [
        {
         id: 1,
         name: "pasta",
         created: "2019-06-24T22:24:50.850468"
         },
        {
         id: 2,
         name: "burger",
         created: "2019-06-24T22:25:25.828976"
        }
      ]
    }

但是当我转到路由'/edit_menu'时,应用程序视图因上面的序列化错误而中断。下面我显示了相关代码:


表格:

1)用户(正在序列化)

class User(db.Model):   
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    restaurant = db.Column(db.String(128))

    menu = db.relationship("Menu",
                    backref=db.backref('user'), 
                    uselist=True)

    def __init__(self, restaurant):
        self.restaurant = restaurant
        self.username = username

    def serialize(self):
       return { 
        'id': self.id,
        'username': self.username,
        'menu' : [ item.serialize() for item in self.menu],
        }

2)菜单(第二个请求后未序列化

class Menu(db.Model):
    __tablename__='menu'

    id = db.Column(db.Integer, primary_key=True)
    created = db.Column(db.DateTime, default=func.now(), nullable=False)

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    dishes = db.relationship('Dish',
                            back_populates='menu',
                            uselist=True)

    def __init__(self, user):
        self.user = user

    def serialize(self):
       """Return object data in easily serializeable format"""
       return { 'id' : self.id,
                'created': self.created.isoformat(),
                'dishes' : [ item.serialize() for item in self.dishes]}

回溯指向我的Flask视图中的错误:

File "/usr/src/app/project/api/routes/menus.py", line 192, in **edit_menu**

正在调用“菜单”的地方(此处可能是关键代码):

@menus_bp.route('/edit_menu', methods=['GET', 'POST'])
def edit_menu():

    response_object = {
        'status': 'fail',
        'message': 'Invalid payload.'
        }
    try:
        user = User.query.filter_by(id=1).first()
        if user.menu == []:
            items = ['item 1', 'item 2', 'item 3', 'item 4', 
                     'item 5', 'item 6', 'item 7', 'item 8']

            template = render_template('seeds.html',
                                        items=items)  
            response_object = {
                          'status': 'success',
                          'message': 'No menus yet',
                          'data': [{"restaurant": user.restaurant,
                                    "seeds": user.seeds,
                                    "content": template}]
                            }
        else:
            all = user.serialize()['menu']
            items = [i['items']for i in all]

            template = render_template('seeds.html', 
                                        items=items)              
            response_object = {
                          'status': 'success',
                          'message': 'Ready to add dishes',
                          'data': [{"restaurant": user.restaurant,
                                    "seeds": user.seeds,
                                    "menu": user.menu,
                                    "content": template}]
                            }
        if request.method == 'POST':
            if 'item' in request.form:
               add = request.form['item']
               Create_or_Update_Menu(user=user)  
               found_playlist = Playlist.query.join(User, User.id == Playlist.user_id).filter(
                                    and_(Playlist.title == item, User.id == 1)).first()
               if not found_playlist:
                   filtered_tracks = filter_dataset_by_item(add)
                   Create_Automatic_Playlists(filtered_dataset=filtered_tracks)  
            return jsonify(response_object), 200    

        if request.method == 'POST':
            if 'item2' in request.form:
                add = request.form['item2']
                Create_or_Update_Menu(user=user) 
                found_playlist = Playlist.query.join(User, User.id == Playlist.user_id).filter(
                                    and_(Playlist.title == item, User.id == 1)).first()
                if not found_playlist:
                    filtered_tracks = filter_dataset_by_item(add)
                Create_Automatic_Playlists(filtered_dataset=filtered_tracks)
            return jsonify(response_object), 200    

    except (exc.IntegrityError, ValueError):
        db.session.rollback()
        return response_object, 400

这是被称为的数据库方法:

def Create_and_Update_Menu(user, dish):
    if user.menu == []:
        menu = Menu(user=user)
        db.session.add(menu)
        db.session.commit()
    else:
        menu = Menu.query.filter_by(user=user).first()

    Dish = Dish(dish=dish)
    db.session.add(dish)
    menu.dishes.append(dish)
    db.session.commit()

    print ('MENU SERIAL',menu.serialize())

    return {"status": True}

完整追溯:

web_1              | Traceback (most recent call last):
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
web_1              |     return self.wsgi_app(environ, start_response)
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
web_1              |     response = self.handle_exception(e)
web_1              |   File "/usr/lib/python3.6/site-packages/flask_restful/__init__.py", line 269, in error_router
web_1              |     return original_handler(e)
web_1              |   File "/usr/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function
web_1              |     return cors_after_request(app.make_response(f(*args, **kwargs)))
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
web_1              |     reraise(exc_type, exc_value, tb)
web_1              |   File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
web_1              |     raise value
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
web_1              |     response = self.full_dispatch_request()
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
web_1              |     rv = self.handle_user_exception(e)
web_1              |   File "/usr/lib/python3.6/site-packages/flask_restful/__init__.py", line 269, in error_router
web_1              |     return original_handler(e)
web_1              |   File "/usr/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function
web_1              |     return cors_after_request(app.make_response(f(*args, **kwargs)))
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
web_1              |     reraise(exc_type, exc_value, tb)
web_1              |   File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
web_1              |     raise value
web_1              |   File "/usr/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
web_1              |     rv = self.dispatch_request()
web_1              |   File "/usr/lib/python3.6/site-packages/flask_debugtoolbar/__init__.py", line 125, in dispatch_request
web_1              |     return view_func(**req.view_args)
web_1              |   File "/usr/src/app/project/api/routes/menus.py", line 195, in edit_menu
web_1              |     return jsonify(response_object), 200
web_1              |   File "/usr/lib/python3.6/site-packages/flask/json/__init__.py", line 321, in jsonify
web_1              |     dumps(data, indent=indent, separators=separators) + '\n',
web_1              |   File "/usr/lib/python3.6/site-packages/flask/json/__init__.py", line 179, in dumps
web_1              |     rv = _json.dumps(obj, **kwargs)
web_1              |   File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps
web_1              |     **kw).encode(obj)
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 201, in encode
web_1              |     chunks = list(chunks)
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 430, in _iterencode
web_1              |     yield from _iterencode_dict(o, _current_indent_level)
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
web_1              |     yield from chunks
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
web_1              |     yield from chunks
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
web_1              |     yield from chunks
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
web_1              |     yield from chunks
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 437, in _iterencode
web_1              |     o = _default(o)
web_1              |   File "/usr/lib/python3.6/site-packages/flask/json/__init__.py", line 81, in default
web_1              |     return _json.JSONEncoder.default(self, o)
web_1              |   File "/usr/lib/python3.6/json/encoder.py", line 180, in default
web_1              |     o.__class__.__name__)
web_1              | TypeError: Object of type 'Menu' is not JSON serializable

注意:第一个请求正在运行。仅从第二个请求开始,问题就会出现。

我在这里想念什么?

1 个答案:

答案 0 :(得分:6)

在您路线中的else语句中,创建一个包含response_object的{​​{1}},但是此值从未被序列化,因此,它实际上是类型{ 'menu': user.menu }的实例。

这可能是第一次全部起作用,因为在调用Menu之前分配了user.menu,所以返回值为Create_or_Update_Menu,该值是可序列化的。第二次实际定义None,这就是发生错误的原因。

此外,您有两个条件相同的if语句,但是如果第一个为true,则始终返回。因此,第二条if语句中的代码永远不会执行。