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

如何遍历POST请求中多个JSON对象并赋值给变量完成入库操作

实现方案与优化建议

1. 正确获取POST提交的JSON数组

首先确保你的Express服务已经配置了JSON解析中间件(一般在入口文件中配置):

app.use(express.json())

配置完成后,客户端提交的JSON数组会直接被解析到req.body中,你直接赋值即可,还可以增加一层兼容逻辑,同时支持提交单个对象和数组场景:

// 直接从req.body获取,兼容单对象/数组提交
const battleList = Array.isArray(req.body) ? req.body : [req.body];

你之前尝试的解构写法是针对单个对象提交的场景,提交数组时不需要提前解构,遍历的时候单独处理每个对象即可。

2. 现有代码可优化的点

你现在写的遍历逻辑可以正常运行,但存在几个可优化的问题:

  • 用for...in遍历数组不符合规范,可能遍历到数组上挂载的非索引自定义属性,建议改用for...of遍历数组
  • 串行await插入数据,数据量较大时接口响应慢,可改用Promise.all并行插入提升效率
  • 构造函数传参太多,很容易写错参数顺序,可改为直接传入整个对象减少冗余代码
  • 直接拼接SQL语句存在SQL注入风险,建议改为参数化查询

3. 优化后完整代码示例

3.1 改造PostBattle类

class PostBattle {
    // 构造函数直接接收单条对战数据对象,不用逐个传参
    constructor(battle) {
        // 批量赋值属性,减少重复代码
        Object.assign(this, battle);
        // 单独处理需要序列化的技能字段
        for (let i = 1; i <= 6; i++) {
            this[`monster_${i}_abilities`] = JSON.stringify(battle[`monster_${i}_abilities`] || '')
        }
    }
    async save() {
        // 改用参数化查询,避免SQL注入
        const sql = `
        INSERT INTO history (
            summoner_id, summoner_level,
            monster_1_id, monster_1_level, monster_1_abilities,
            monster_2_id, monster_2_level, monster_2_abilities,
            monster_3_id, monster_3_level, monster_3_abilities,
            monster_4_id, monster_4_level, monster_4_abilities,
            monster_5_id, monster_5_level, monster_5_abilities,
            monster_6_id, monster_6_level, monster_6_abilities,
            created_date, match_type, mana_cap, ruleset, inactive,
            battle_queue_id, player_rating_initial, player_rating_final, winner
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `
        // 按顺序拼接参数
        const params = [
            this.summoner_id, this.summoner_level,
            this.monster_1_id, this.monster_1_level, this.monster_1_abilities,
            this.monster_2_id, this.monster_2_level, this.monster_2_abilities,
            this.monster_3_id, this.monster_3_level, this.monster_3_abilities,
            this.monster_4_id, this.monster_4_level, this.monster_4_abilities,
            this.monster_5_id, this.monster_5_level, this.monster_5_abilities,
            this.monster_6_id, this.monster_6_level, this.monster_6_abilities,
            this.created_date, this.match_type, this.mana_cap, this.ruleset, this.inactive,
            this.battle_queue_id, this.player_rating_initial, this.player_rating_final, this.winner
        ]
        const [newPost, _] = await db.execute(sql, params)
        return newPost
    }
}

3.2 改造接口逻辑

exports.createNewPost = async (req, res, next) => {
    try {
        // 获取对战列表,兼容单对象/数组提交
        const battleList = Array.isArray(req.body) ? req.body : [req.body]
        // 并行生成实例+入库,效率更高
        const savePromises = battleList.map(battle => {
            const post = new PostBattle(battle)
            return post.save()
        })
        const result = await Promise.all(savePromises)
        console.log(`成功插入${result.length}条对战记录`)
        // 返回成功响应
        res.status(201).json({ success: true, count: result.length })
    } catch (err) {
        // 统一捕获错误处理
        next(err)
    }
}

补充说明

如果你的场景要求严格保证入库顺序,或者数据量极大需要避免数据库压力过高,可以把Promise.all改回串行for...of遍历:

for (const battle of battleList) {
    const post = new PostBattle(battle)
    await post.save()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:45:07