You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask RESTful Put接口JSON解码错误排查求助

解决Flask-RESTful中PUT请求的JSONDecodeError问题

问题原因分析

你遇到的requests.exceptions.JSONDecodeError本质是服务器返回的响应不是有效的JSON格式,主要有三个核心原因:

  1. 数据库表未初始化:代码未创建SQLite数据库表,首次运行插入数据时触发服务器500错误,返回HTML错误页面而非JSON。
  2. abort用法不规范:直接使用abort(message='xxx')会返回默认的500错误HTML页面,而非Flask-RESTful规范的JSON错误响应。
  3. 请求数据格式不符合RESTful规范:requests.put默认用表单格式发送数据,虽能被解析,但更规范的REST请求应使用JSON格式。

解决方案

1. 初始化数据库表

在main.py的启动逻辑中添加表创建代码,确保首次运行自动生成数据库表:

if __name__ == "__main__":
    with app.app_context():
        db.create_all()  # 创建所有模型对应的数据库表
    app.run(debug=True)

2. 修正abort的用法

给abort指定正确的HTTP状态码,让Flask-RESTful返回JSON格式的错误响应:

# get方法中修改abort逻辑
if not result:
    abort(404, message='could not find the video with that id')

# put方法中修改abort逻辑
if result:
    abort(409, message='video id taken')

3. 规范客户端请求格式

在test.py中使用json参数发送请求,确保数据以JSON格式传递:

response = requests.put(
    BASE + f'video/{32}',
    json={"likes": 10353, 'name': 'studywithme for 2 hours', 'views': 12342000}
)

修改后的完整代码

main.py

from flask import Flask, request
from flask_restful import Api, Resource, reqparse, abort, fields, marshal_with
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
api = Api(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
db = SQLAlchemy(app)


class VideoModel(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    views = db.Column(db.Integer, nullable=False)
    likes = db.Column(db.Integer, nullable=False)

    def __repr__(self):
        return f'Video(name = {self.name},views = {self.views}, likes = {self.likes})'


video_put_args = reqparse.RequestParser()
video_put_args.add_argument(
    'name', type=str, help='name of the video is required', required=True)
video_put_args.add_argument(
    'views', type=int, help='views on the video is required', required=True)
video_put_args.add_argument(
    'likes', type=int, help='likes on the video is required', required=True)

resource_fields = {'id': fields.Integer, 'name': fields.String,
                   'views': fields.Integer, 'likes': fields.Integer}


class Video(Resource):
    @marshal_with(resource_fields)
    def get(self, video_id):
        result = VideoModel.query.filter_by(id=video_id).first()
        if not result:
            abort(404, message='could not find the video with that id')
        return result

    @marshal_with(resource_fields)
    def put(self, video_id):
        args = video_put_args.parse_args()
        result = VideoModel.query.filter_by(id=video_id).first()
        if result:
            abort(409, message='video id taken')
        video = VideoModel(
            id=video_id, name=args['name'], views=args['views'], likes=args['likes'])
        db.session.add(video)
        db.session.commit()
        return video


api.add_resource(Video, "/video/<int:video_id>")

if __name__ == "__main__":
    with app.app_context():
        db.create_all()
    app.run(debug=True)

test.py

import requests

BASE = "http://127.0.0.1:5000/"

response = requests.put(
    BASE + f'video/{32}',
    json={"likes": 10353, 'name': 'studywithme for 2 hours', 'views': 12342000}
)

print(response.json())

修改完成后,服务器会返回标准JSON响应,客户端可正常解析response.json()获取结果。

内容的提问来源于stack exchange,提问作者Studywith Me

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:17:11