Objection JS插入数据报错NJS-012:参数2存在无效绑定数据类型
问题根因
从Knex打印的绑定参数日志可以直接定位问题:
- 对应
CONTENT_IDS字段(CLOB类型,存JSON数组)的绑定值为[ { id: 11111 } ],是包含普通JS对象的数组,既不符合字段约定的数字数组格式,也没有被序列化为JSON字符串。node-oracledb驱动无法将未序列化的JS对象/数组直接映射为Oracle支持的绑定类型,直接触发NJS-012: encountered invalid bind data type错误。 - 路由层Joi校验规则写法错误:最外层缺少
Joi.object()包裹,字段校验规则错误嵌套了Joi实例作为example值,导致校验逻辑完全失效,没有拦住格式非法的入参,直接把不符合约定的结构传到了数据库层。 - Objection.js模型没有配置JSON字段自动序列化逻辑,存JSON的CLOB字段(counts、content_ids、search_query)写入时没有统一做JSON字符串转换,部分场景下原始JS结构会直接传给驱动触发类型错误。
修复方案
按顺序做以下修改即可解决:
- 修正Joi入参校验规则,拦截非法格式入参
替换原有validate.payload配置,明确字段格式要求,自动剔除多余字段:
validate: { payload: Joi.object({ counts: Joi.object({ total: Joi.number().integer().default(0), completed: Joi.number().integer().default(0), failed: Joi.number().integer().default(0), queued: Joi.number().integer().default(0), }).default({}), type: Joi.string().valid('manual').required(), content_ids: Joi.array().items(Joi.number().integer()).default([]), search_query: Joi.object({ query: Joi.string().required(), }).default({}), republishing_reason: Joi.string().allow('', null), duration: Joi.number().integer().required(), }).options({ stripUnknown: true, abortEarly: false }) }
- 给MassRepublishJob模型增加JSON字段自动序列化/反序列化逻辑,确保写入CLOB字段的都是合法JSON字符串,读取时自动转回JS结构:
// 在MassRepublishJob模型类中添加配置 static get jsonAttributes() { return ['counts', 'content_ids', 'search_query']; } // 若使用的Objection版本较旧,jsonAttributes配置不生效,添加以下两个方法 $formatDatabaseJson(json) { const formatted = super.$formatDatabaseJson(json); ['counts', 'content_ids', 'search_query'].forEach(field => { if (formatted[field] !== undefined) { formatted[field] = JSON.stringify(formatted[field]); } }); return formatted; } $parseDatabaseJson(json) { const parsed = super.$parseDatabaseJson(json); ['counts', 'content_ids', 'search_query'].forEach(field => { if (parsed[field] && typeof parsed[field] === 'string') { try { parsed[field] = JSON.parse(parsed[field]); } catch (err) { // 兼容库中已存在的非JSON格式脏数据 } } }); return parsed; }
- 校验修复后,若前端传入的content_ids仍为
[{id: 11111}]格式,Joi会直接返回400参数错误,不会再走到数据库插入逻辑;如果是业务逻辑需要支持该格式,在序列化前先提取数组项中的id值,转为纯数字数组即可。
内容的提问来源于stack exchange,提问作者Quan Khuc
相关产品推荐
相关产品推荐

