【问题标题】:TypeError: Object is not JSON serializableTypeError:对象不是 JSON 可序列化的
【发布时间】:2019-06-25 05:09:13
【问题描述】:

我对遇到的以下错误很感兴趣:

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]}

traceback 指向我的 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

注意:第一个请求有效。只有从第二个请求开始,问题才会出现。

我在这里错过了什么?

【问题讨论】:

    标签: json serialization flask-sqlalchemy


    【解决方案1】:

    在你的路由的 else 语句中,你创建了一个包含 { 'menu': user.menu }response_object,但这个值永远不会被序列化,所以这实际上是一个 Menu 类型的实例。

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

    另外,你有两个条件相同的 if 语句,但如果第一个为真,那么你总是返回。因此,第二个 if 语句中的代码永远不会执行。

    【讨论】:

      猜你喜欢
      • 2017-09-23
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 2021-11-13
      • 2018-09-22
      • 2019-01-17
      • 2019-12-07
      相关资源
      最近更新 更多