Node.js YelpCamp项目更新露营地时触发"campground is required"校验错误求助
错误原因
你的Joi校验逻辑明确要求请求体顶层必须包含必填的campground对象,用于包裹露营地的title、price、location、description等字段。触发报错的核心原因是提交更新请求时,实际传入的req.body中不存在campground属性,导致校验不通过。
最常见的诱因是前端表单字段未加命名前缀:你编写更新表单时,输入框的name属性直接写了title、price这类字段名,没有加campground[xxx]的前缀,Express的urlencoded中间件就不会把这些字段聚合为req.body.campground对象。
修复方案
方案1:修改前端表单字段命名(推荐,适配现有逻辑)
将更新页面中所有露营地相关输入框的name属性,添加campground[ ]前缀,示例如下:
<!-- 修改前 --> <input type="text" name="title" placeholder="露营地名称"> <input type="number" name="price" placeholder="价格"> <!-- 修改后 --> <input type="text" name="campground[title]" placeholder="露营地名称"> <input type="number" name="campground[price]" placeholder="价格">
修改后请求提交时,字段会自动聚合为req.body.campground对象,匹配现有Joi校验规则,无需修改后端代码。
方案2:调整后端校验与业务逻辑(无需修改前端)
如果不想改动前端传参结构,直接修改后端的Joi规则和更新逻辑即可:
- 修改Joi校验规则,移除外层
campground对象的嵌套要求:
const Joi = require('joi'); module.exports.campgroundSchema = Joi.object({ title: Joi.string().required(), price: Joi.number().required().min(0), location: Joi.string().required(), description: Joi.string().required() });
- 修改更新露营地的业务代码,直接从
req.body取字段:
module.exports.updateCampground = async (req, res) => { const { id } = req.params; // 把原来的req.body.campground改为req.body const campgrounds = await campground.findByIdAndUpdate(id, { ...req.body }); const imgs = req.files.map((f) => ({ url: f.path, filename: f.filename })); campgrounds.images.push(...imgs); await campgrounds.save(); req.flash('success', 'Successfully updated Campground'); res.redirect(`/campgrounds/${campgrounds._id}`); };
内容的提问来源于stack exchange,提问作者Samip
相关产品推荐
相关产品推荐

