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

Flask中json.loads()报错,CLI中相同代码运行正常

Flask路由调用API出现JSONDecodeError但CLI运行正常问题排查

问题描述

我有一个作为模块的sl.py文件和主Flask文件app.py,sl.py中的get_shloka函数从API获取JSON数据,提取所需内容存入info列表用于HTML展示。通过Flask的/shlok路由调用该函数时,抛出json.decoder.JSONDecodeError错误,但在CLI中使用相同参数调用该函数却能正常运行,且HTML无相关错误。

代码展示

sl.py

def get_shloka(ch, v):
    url = f"https://bhagavadgitaapi.in/slok/{ch}/{v}"
    r = requests.get(url)
    r = r.text
    r = json.loads(r)
    print(type(r))

    info = [r["slok"], r["transliteration"], r["purohit"]["et"]]

    return info

app.py

@app.route("/", methods = ["GET", "POST"])
def home():
    if request.method == 'POST':
        ch = request.form['ch']
        shlok = request.form['shlok']
        return redirect(url_for('shlok', ch=ch, shlok=shlok))
    
    return render_template("index.html")

@app.route("/shlok", methods = ["GET", "POST"])
def shlok():
    ch = request.form.get('ch')
    shlok = request.form.get('shlok')

    shloka = get_shloka(ch, shlok)

    return render_template("shlok.html", shloka=shloka)

报错信息

File "/home/risen/dev/gita-reader/app.py", line 35, in shlok
    shloka = get_shloka(ch, shlok)
File "/home/risen/dev/gita-reader/sl.py", line 8, in get_shloka
    r = json.loads(r)
File "/usr/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
File "/usr/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.10/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

原因分析

核心问题是参数传递与获取不匹配:

  • 首页POST提交表单后,通过redirect跳转到/shlok路由,此时ch和shlok是作为URL参数(GET参数)传递的;
  • 但/shlok路由里用request.form.get()获取参数,而GET请求不会携带form数据,导致ch和shlok的值为None;
  • 拼接的API URL变成https://bhagavadgitaapi.in/slok/None/None,API返回的不是有效JSON(可能是空内容或错误页面),调用json.loads()时抛出解码错误;
  • CLI中直接传入有效参数,API返回正常JSON,所以函数运行无问题。

解决方案

1. 修正/shlok路由的参数获取方式

将request.form.get()改为request.args.get(),适配GET请求的URL参数:

@app.route("/shlok", methods = ["GET", "POST"])
def shlok():
    ch = request.args.get('ch')
    shlok = request.args.get('shlok')

    # 增加参数校验,避免空值调用API
    if not ch or not shlok:
        return "请提供有效的章节和偈颂编号", 400

    shloka = get_shloka(ch, shlok)

    return render_template("shlok.html", shloka=shloka)

2. 优化sl.py的代码健壮性

直接使用requests的r.json()方法解析响应,同时增加异常捕获,处理请求失败或数据解析错误的情况:

import requests
import json

def get_shloka(ch, v):
    try:
        url = f"https://bhagavadgitaapi.in/slok/{ch}/{v}"
        r = requests.get(url)
        # 检查请求是否成功(状态码200-299)
        r.raise_for_status()
        # 直接解析JSON响应
        data = r.json()
        info = [data["slok"], data["transliteration"], data["purohit"]["et"]]
        return info
    except requests.exceptions.RequestException as e:
        print(f"API请求失败: {e}")
        return []
    except (KeyError, json.JSONDecodeError) as e:
        print(f"数据解析错误: {e}")
        return []

3. 兼容GET和POST请求(可选)

如果/shlok路由需要支持直接表单提交(POST),可以同时兼容两种参数获取方式:

@app.route("/shlok", methods = ["GET", "POST"])
def shlok():
    ch = request.form.get('ch') or request.args.get('ch')
    shlok = request.form.get('shlok') or request.args.get('shlok')

    if not ch or not shlok:
        return "请提供有效的章节和偈颂编号", 400

    shloka = get_shloka(ch, shlok)

    return render_template("shlok.html", shloka=shloka)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 12:47:52