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

如何在RTK Query baseQuery中实现请求体与参数驼峰转蛇形

RTK Query 请求参数/请求体蛇形命名转换实现方案

你的判断是对的,请求侧的键名转换统一放在自定义baseQuery层实现是最优解,不需要在每个endpoint单独写重复逻辑,维护成本最低。

实现核心逻辑:

  • 调用原始baseQuery发起请求前,拦截传入的请求参数,把普通对象类型的body(请求体)和params(URL查询参数)的键名从驼峰转为下划线
  • 请求返回后保留你原有的响应数据驼峰转换逻辑即可

注意要跳过FormData、Blob、文件流这类特殊格式的请求体,避免破坏上传类接口的正常逻辑。


完整实现代码

假设你用的是RTK Query官方提供的fetchBaseQuery,完整代码如下:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
// 键名转换工具,可引入第三方库如humps,也可以自己实现
import { camelizeKeys, snakifyKeys } from './utils/keyTransform'

// 初始化原始baseQuery实例
const rawBaseQuery = fetchBaseQuery({ baseUrl: '/your-api-prefix' })

const api = createApi({
  reducerPath: 'API',
  baseQuery: async (args, api, extraOptions) => {
    let finalArgs = args

    // 仅当args是请求配置对象(而非纯字符串URL)时处理参数
    if (typeof args === 'object' && !extraOptions?.skipKeyTransform) {
      finalArgs = { ...args }

      // 处理请求体:跳过FormData、Blob等特殊格式
      if (
        finalArgs.body &&
        typeof finalArgs.body === 'object' &&
        !(finalArgs.body instanceof FormData) &&
        !(finalArgs.body instanceof Blob) &&
        !(finalArgs.body instanceof ArrayBuffer)
      ) {
        finalArgs.body = snakifyKeys(finalArgs.body)
      }

      // 处理URL查询参数
      if (finalArgs.params && typeof finalArgs.params === 'object') {
        finalArgs.params = snakifyKeys(finalArgs.params)
      }
    }

    // 发起请求
    const result = await rawBaseQuery(finalArgs, api, extraOptions)
    const { data, meta, error } = result

    // 保留原有响应转驼峰逻辑
    return {
      ...result,
      data: data ? camelizeKeys(data) : data
    }
  },
  endpoints: () => ({}),
})

附:原生JS实现键名转换工具

如果不想引入第三方依赖,可以直接用下面的递归转换函数,覆盖绝大多数普通对象、数组嵌套场景:

// 驼峰字符串转下划线
const toSnake = (str) => str.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`)
// 下划线字符串转驼峰
const toCamel = (str) => str.replace(/_([a-z])/g, (_, char) => char.toUpperCase())

// 递归遍历对象转换键名
const keyTransform = (target, transformFn) => {
  if (Array.isArray(target)) return target.map(item => keyTransform(item, transformFn))
  if (target && typeof target === 'object' && target.constructor === Object) {
    return Object.keys(target).reduce((acc, key) => {
      acc[transformFn(key)] = keyTransform(target[key], transformFn)
      return acc
    }, {})
  }
  return target
}

const snakifyKeys = (data) => keyTransform(data, toSnake)
const camelizeKeys = (data) => keyTransform(data, toCamel)

扩展说明

  • 如果你用的是axios-base-query或者其他自定义baseQuery,逻辑完全通用,只需要在调用原始baseQuery前修改传入的请求配置即可
  • 代码里预留了skipKeyTransform标记,如果有个别接口不需要做键名转换,调用时传入extraOptions: { skipKeyTransform: true }即可跳过转换
  • 如果需要处理请求头里的特殊字段,也可以用同样的思路在请求前修改finalArgs.headers配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:48:53