NodeJS 如何使用Joi验证对象数组?

bvjveswy  于 2022-11-29  发布在  Node.js
关注(0)|答案(6)|浏览(186)

我将一个对象数组发送到后端,其中每个对象都包含一个服务名称。

[{"serviceName":"service1"},
{"serviceName":"service2"},..]

当我在后端获得数组时,我希望验证数组中的每个对象都具有serviceName属性。
我已经写了下面的代码,但是即使我传递了有效的数组,我还是得到了验证错误。

var Joi = require('joi');
var service = Joi.object().keys({
  serviceName: Joi.string().required()
});

var services = Joi.array().ordered(service);

var test = Joi.validate([{serviceName:'service1'},{serviceName:'service2'}],services)

对于上面的代码,我总是得到验证错误消息

"value" at position 1 fails because array must contain at most 1 items
wgeznvg7

wgeznvg71#

ordered替换为items即可。

let Joi = require('joi')
let service = Joi.object().keys({
  serviceName: Joi.string().required(),
})

let services = Joi.array().items(service)

let test = Joi.validate(
  [{ serviceName: 'service1' }, { serviceName: 'service2' }],
  services,
)

如需参考,请单击此处

emeijp43

emeijp432#

下面是一个基本的/更清晰的例子。

{
    "data": [
            {
        "keyword":"test",
        "country_code":"de",
        "language":"de",
        "depth":1
            }
        ]
    }

下面是Joi验证:

seoPostBody: {
    body: {
      data: Joi.array()
        .items({
          keyword: Joi.string()
            .required(),
          country_code: Joi.string()
            .required(),
          language: Joi.string()
            .required(),
          depth: Joi.number()
            .required(),
        }),
    },
  };
  • 这是我在NodeJs中所做的,可能需要为其他平台做一些细微的更改 *
ejk8hzay

ejk8hzay3#

const test = {
body: Joi.array()
    .items({
        x: Joi.string().required(),
        y: Joi.string().required(),
        z: Joi.string().required(),
        date: Joi.string().required(),
    })
};
4ktjp1zp

4ktjp1zp4#

只是想让它更清楚。我目前使用“@hapi/joi:16.1.7”。
假设您希望模式验证这个对象数组。

const example = [
   {
      "foo": "bar",
      "num": 1,
      "is_active": true,
   }
];

那么模式的规则应该是:

var validator = require('@hapi/joi');

const rules = validator.array().items(
    validator.object(
        foo: validator.string().required(),
        num: validator.number().required(),
        is_active: validator.boolean().required(),
    ),
);

const { error } = rules.validate(example);
col17t5w

col17t5w5#

对于Joi,您可以使用下面对我来说很好的方法,这将验证阵列必须至少有一个关键字为serviceName的对象-

const Joi = require('joi');
const itemsArray = Joi.array().items(
            Joi.object({
                serviceName: Joi.string().required(),
            })
        ).min(1).required();

        const itemSchema = Joi.array().items(itemsArray).when('checkout_type', {
            is: 'guest',
            then: Joi.array().required(),
        }).required();

let schema = Joi.object().keys({
        items: Joi.alternatives().try(itemsArray, itemSchema).required(),
    });
zvokhttg

zvokhttg6#

像这样的库很棒,但是如果我们能以一种更无缝的方式使用它们,比如在请求管道中,不是更好吗?让我们先看看如何在Node.js的Express应用中使用Joi:

const Joi = require('joi'); 
app.post('/blog', async (req, res, next) => { 
  const { body } = req; const 
  blogSchema = Joi.object().keys({ 
    title: Joi.string().required 
    description: Joi.string().required(), 
    authorId: Joi.number().required() 
  }); 
  const result = Joi.validate(body, blogShema); 
  const { value, error } = result; 
  const valid = error == null; 
  if (!valid) { 
    res.status(422).json({ 
      message: 'Invalid request', 
      data: body 
    }) 
  } else { 
    const createdPost = await api.createPost(data); 
    res.json({ message: 'Resource created', data: createdPost }) 
  } 
});

上面的方法是可行的,但是我们必须对每条路线:
1.创建模式
1.调用validate()函数
没有更好的词来形容它,它缺乏优雅。我们想要看起来光滑的东西

构建中间件

让我们看看我们是否可以将其稍微重建为中间件。Express中的中间件只是我们可以在需要时插入请求管道的东西。在我们的例子中,我们希望尝试验证我们的请求,并尽早确定是否值得继续处理或中止它。
让我们来看看中间件。它只是一个函数:

const handler = (req, res, next) = { // handle our request } 
const middleware = (req, res, next) => { // to be defined } 
app.post( '/blog', middleware, handler )

如果我们能够为中间件提供一个模式,那么我们在中间件函数中所要做的就是这样的事情:

(req, res, next) => { 
  const result = Joi.validate(schema, data) 
}

我们可以为所有模式创建一个带有工厂函数和模块的模块。让我们先看一下工厂函数模块:

const Joi = require('joi'); 
const middleware = (schema, property) => { 
  return (req, res, next) => { 
  const { error } = Joi.validate(req.body, schema); 
  const valid = error == null; 
  
  if (valid) { 
    next(); 
  } else { 
    const { details } = error; 
    const message = details.map(i => i.message).join(',');
 
    console.log("error", message); 
   res.status(422).json({ error: message }) } 
  } 
} 
module.exports = middleware;

接下来,让我们为所有模式创建一个模块,如下所示:

// schemas.js 
const Joi = require('joi') 
const schemas = { 
  blogPOST: Joi.object().keys({ 
    title: Joi.string().required 
    description: Joi.string().required() 
  }) 
  // define all the other schemas below 
}; 
module.exports = schemas;

好了,让我们回到应用程序文件:

// app.js 
const express = require('express') 
const cors = require('cors'); 
const app = express() 
const port = 3000 
const schemas = require('./schemas'); 
const middleware = require('./middleware'); 
var bodyParser = require("body-parser"); 

app.use(cors()); 
app.use(bodyParser.json()); 
app.get('/', (req, res) => res.send('Hello World!')) 
app.post('/blog', middleware(schemas.blogPOST) , (req, res) => { 
  console.log('/update'); 
  res.json(req.body); 
}); 
 app.listen(port, () => console.log(`Example app listening on port ${port}!`))

相关问题