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

FastAPI解析嵌套数组格式HTTP GET请求URL参数的问题求助

解决FastAPI中PHP风格嵌套URL查询参数的解析问题

我刚好遇到过类似的场景,FastAPI默认对products[0][id]这种PHP风格的嵌套查询参数支持不够直接——这也是你之前用List或者直接传products参数返回None的原因,FastAPI默认期望的是点分隔的嵌套格式(比如products[0].id),而非方括号的结构。

下面给你两种更优的解决方案,根据你的场景选择:

方案一:自定义依赖项(推荐,兼容现有参数格式)

这种方式可以直接解析你当前的参数格式,同时利用Pydantic做类型验证和转换,代码更健壮可复用:

首先定义产品的Pydantic模型,用来做类型校验:

from pydantic import BaseModel
from fastapi import FastAPI, Request, Depends
from typing import List

class Product(BaseModel):
    id: str
    count: int  # 自动将字符串转换为整数,还会做合法性校验

app = FastAPI()

然后写一个自定义依赖函数,专门解析这种方括号格式的参数:

def parse_php_style_products(request: Request) -> List[Product]:
    param_dict = dict(request.query_params)
    products_temp = {}
    
    # 遍历所有查询参数,解析键名中的索引和字段
    for key, value in param_dict.items():
        # 处理类似products[0][id]的键,拆分出索引和字段
        key_parts = key.strip('[]').split('][')
        if len(key_parts) != 3 or key_parts[0] != "products":
            continue  # 跳过非products前缀的参数
        
        idx = key_parts[1]
        field = key_parts[2]
        
        # 按索引分组存储产品字段
        if idx not in products_temp:
            products_temp[idx] = {}
        products_temp[idx][field] = value
    
    # 按索引排序,确保顺序正确,然后转换为Product模型列表
    sorted_products = [products_temp[str(i)] for i in range(len(products_temp))]
    return [Product(**product_data) for product_data in sorted_products]

最后在接口中使用这个依赖:

@app.get("/api/")
def get_products(products: List[Product] = Depends(parse_php_style_products)):
    print(products)
    # 输出示例:[Product(id='ABC123', count=1), Product(id='ABC124', count=2)]
    return {"products": products}

这个方案的优势:

  • 自动做类型转换和校验(比如count会从字符串转成整数,传非数字会直接返回422错误)
  • 即使参数顺序混乱(比如products[1]的参数先出现),也能按索引正确排序
  • 代码可复用,其他接口需要解析类似格式参数时直接用这个依赖就行

方案二:协调前端修改参数格式(更简洁)

如果可以协调前端改成FastAPI原生支持的嵌套参数格式(用点分隔),比如:

.../api/?products[0].id=ABC123&products[0].count=1&products[1].id=ABC124&products[1].count=2

那你只需要直接用Pydantic模型+List就能自动解析,不需要额外代码:

from pydantic import BaseModel
from fastapi import FastAPI, Query
from typing import List

class Product(BaseModel):
    id: str
    count: int

app = FastAPI()

@app.get("/api/")
def get_products(products: List[Product] = Query(None)):
    print(products)
    return {"products": products}

对比你之前的实现

你之前的循环按每两个参数取的方式有个明显缺陷:如果参数顺序不对、或者某个产品的字段缺失,就会导致解析结果错误。而上面的方案一通过按索引分组的方式,彻底避免了这个问题,同时还增加了类型校验,稳定性更高。

内容的提问来源于stack exchange,提问作者Filip Bartoš

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:14:11