本文介绍一个用于前后端接口数据格式转换的JavaScript工具函数。该函数支持下划线命名与驼峰命名之间的双向互转,处理对象和数组类型数据,通过递归实现深层嵌套转换,并保留原始数据结构。
一、前言
临近年底,公司业务相对轻松,作者利用这段空闲时间,尝试基于React 18和Koa2技术栈开发一个后台管理系统。
在接口数据交互过程中,发现后端数据库存储采用下划线命名规范,而前端开发习惯使用驼峰命名。若直接将数据库数据返回给前端,代码可读性和维护性较差。由于未找到合适的现成工具包,作者自行编写了一个转换函数,供有类似需求的开发者参考使用。
二、思路
- 后端返回给前端的数据通常只有数组或对象两种格式,因此封装的函数只需针对这两种类型进行处理。
- 该函数需同时支持两种转换场景:一是后端返回数据时,将下划线命名转换为驼峰命名;二是前端提交数据时,将驼峰命名转换为下划线命名。
- 函数接收两个参数:data(源数据,可以是数组或对象)和type(转换模式,'hump'表示下划线转驼峰,'line'表示驼峰转下划线)。
- 首先判断传入的data类型。若为对象,则将其转换为数组形式;若为数组,则直接处理。随后对数据进行深拷贝,以避免修改原始数据导致意外的堆污染问题。
- 由于数据层级不确定,需采用递归方式处理。对对象的value进行判断,若value仍为对象,则继续递归处理。
- 遍历data,使用for...in遍历每个对象的键值对。根据type参数执行相应转换逻辑。对于下划线转驼峰的情况,若下划线位于字符串最前端,则直接删除该下划线。
- 对象键值对的修改策略为:先保存原value,修改key后,使用delete删除原key:value对,再重新赋值。作者注:此方法可能不够优雅,欢迎提供更好方案。
- 上述处理过程中,为方便操作将对象转为数组格式。处理完成后,需将原为对象的数据重新转换回对象格式并返回,以保持原始数据结构不变。
三、代码
/** 返回数据下划线驼峰互转函数封装
* @param {data} 'obj或ary'
* @param {type} 'hump' 为下划线转驼峰,'line' 为驼峰转下划线
* @return {Array||Object}
*/
export const formatHumpLineTransfer = (data, type = 'hump') => {
// 判断传入的值是对象还是数组
const newData =
Object.prototype.toString.call(data) === '[object Object]'
? [JSON.parse(JSON.stringify(data))]
: JSON.parse(JSON.stringify(data))
function toggleFn(list) {
list.forEach((item) => {
for (const key in item) {
// 如果值为对象
if (Object.prototype.toString.call(item[key]) === '[object Object]') {
toggleFn([item[key]])
}
// 如果值为数组
else if (Object.prototype.toString.call(item[key]) === '[object Array]') {
toggleFn(item[key])
}
// 下划线 转 驼峰
else if (type === 'hump') {
const keyArr = key.split('_')
let str = ''
if (keyArr.length > 1) {
keyArr.forEach((item, index) => {
if (item) {
if (index) {
const arr = item.split('')
arr[0] = arr[0].toUpperCase()
str += arr.join('')
} else {
str += item
}
}
if (!item) {
keyArr.splice(0, 1)
}
})
const newValue = item[key]
delete item[key]
item[str] = newValue
}
}
// 驼峰 转 下划线
else if (type === 'line') {
const regexp = /^[A-Z]+$/
const newKey = key.split('')
const newValue = item[key]
newKey.forEach((item2, index2) => {
if (regexp.test(item2)) {
newKey[index2] = '_' + item2.toLowerCase()
}
})
delete item[key]
item[newKey.join('')] = newValue
}
}
})
}
toggleFn(newData)
// 因为上面操作为了方便操作,会将对象转化为数组格式,操作完后,需要将原先是对象的重新转化为对象
if (Object.prototype.toString.call(data) === '[object Object]') {
let obj = null
newData.forEach((item) => (obj = item))
return obj
} else {
return newData
}
}
四、效果
转换前:

转换后:

结语
希望上述内容能帮助遇到相同问题的开发者。更多关于JS封装转换前后端接口数据格式的资料,请关注本站其他相关文章!