web-dev-qa-db-ja.com

Joiを使用してオブジェクトの配列を検証する方法は?

バックエンドにオブジェクトの配列を取得しています。各オブジェクトにはサービス名が含まれています。構造は以下のようになります

[{"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
28
zakir

ordereditemsに置き換えると動作します。

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,
)

参考のために ここをクリック

65
zakir

これを試してみることもできます。おそらく、データの長さと、thridparty APIからの応答の場合に返される実際のデータはわかりません。その場合、これは役に立つと思います。 lodashの_.each機能を活用してデータを検証しようとしています

//readCourseObject.js
const Joi = require('joi');
const CourseObjectKeys = Joi.object().keys({
    appObj: Joi.string().strict().required(),
    id:Joi.number().strict().required(),
    name: Joi.string().strict().min(3).required(),
    version: Joi.number().strict().min(1).required()

});

module.exports = CourseObjectKeys;


//I am trying to read a json file here for simplicity
//ReadCourseContents.js
const fs = require('fs');
const path = require('path');

const ErrorConstant = require('../models/errorConstants');
const errorConstantObj = new ErrorConstant();

const _ = require('lodash');
const Joi = require('joi');
const courseObjectKeys = require('../models/coureObjectKeys');

const CourseValidator = require('../validators/courseValidation');
const courseValidatorObj  = new CourseValidator();

let filePath = path.resolve(__dirname+'./../../resources/courseData.json');

class ReadCourseDataJsonSync{
    readFile(requestParamId){

        let bufferedData = fs.readFileSync(filePath);
        console.log('bufferedData course data json>', bufferedData);
        let jsonCourseData = JSON.parse(bufferedData);
        console.log('json data read,', jsonCourseData);  


        if(requestParamId === null){
            let courseArray = this.readAllData(jsonCourseData)
            console.log('course array before being retruned:',courseArray);
           return courseArray;
        }else {
           return this.readSelectedId(jsonCourseData, requestParamId);
        }
    }

    //Read All data
    readAllData(jsonData){
        let courseObjectKeysArray = [];
        if( _.isArray(jsonData.courseDatas)){
            _.each(jsonData.courseDatas, (data)=>{
                console.log('each element in json:', data);
                Joi.validate({appObj:'sample', id:jsonData.id, name: name.course_name, version:data.version}, courseObjectKeys, (err, value)=>{
                    if(err){
                        console.log('error is thrown', err);
                        errorConstantObj.setErrorStatus(500);
                        errorConstantObj.setErrorMessage('Invalid course data json.Find stack trace in the errorObj');
                        errorConstantObj.setErrorObject(err);
                        errorConstantObj.setErrorDescription('Cannot add course json data because of invalid data present in json');
                        return errorConstantObj;
                    }else{
                        courseObjectKeysArray.Push(data);
                    }
                });

            });


            console.log('courseObjectKeys', courseObjectKeysArray);
            return courseObjectKeysArray;
        }else {
            console.log('only one element in json:', jsonData);
            Joi.validate({appObj:'sample', id:jsonData.id, name: jsonData.course_name, sdsd:data.version}, courseObjectKeys, (err, value)=>{
                if(err){
                    console.log('error is thrown', err);
                    errorConstantObj.setErrorStatus(500);
                    errorConstantObj.setErrorMessage('Invalid course data json.Find stack trace in the errorObj');
                    errorConstantObj.setErrorObject(err);
                    errorConstantObj.setErrorDescription('Cannot add course json data because of invalid data present in json');
                    return errorConstantObj;
                }else{
                    return value;
                }
            });

        }
    }

    //read a single ID
    readSelectedId(jsonData, requestParamId){ 
        let value;
       console.log('validation of id:',courseValidatorObj.validateCourse(true, requestParamId));
       if(courseValidatorObj.validateCourse(true, requestParamId)){
        value =  _.find(jsonData, {requestParamId});
        console.log('value found in array', value);
        return value;
       }else{
          const err = new Error('Incorrect id passsed for the course. No data to fetch');
        errorConstantObj.setErrorStatus(420);
        errorConstantObj.setErrorMessage('Incorrect id passsed for the course. No data to fetch');
        errorConstantObj.setErrorObject(err);
        errorConstantObj.setErrorDescription('Desc- Incorrect id passsed for the course. No data to fetch');
        return errorConstantObj;
       }    
    }

}



module.exports = ReadCourseDataJsonSync;

注:簡単にするために、同期呼び出しが使用されます

0
Joey587