Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we write a Joi schema for different request types?

I've been trying to create a schema. It represents my object, which is like {name:"Joe Doe", id:"1234567890"} But on the first request which is for creating new one; it should not have an id parameter in the object. Otherwise it might be meaning an update to consumer...

Would you have any idea about the best way to implement it?

What I need as a joi schema;

joi.object().keys({
    id: joi.string().forbidden() or required(),
    name: joi.string(),
    ...

Sample requests;

Create:

POST Request... 'api/v1/item/'

Object : {name:"Joe Doe"}

Update:

PUT Request... 'api/v1/item/'

Object : {id:"1234567890", name:"Joe Doe"}

like image 451
atasoyh Avatar asked Dec 30 '19 15:12

atasoyh


People also ask

What is a joi schema?

Hapi Joi is an object schema description language and validator for JavaScript objects. With Hapi Joi, we create blueprints or schemas for JavaScript objects (an object that stores information) to ensure validation of key information.

Which is better express validator or Joi?

Joi can be used for creating schemas (just like we use mongoose for creating NoSQL schemas) and you can use it with plain Javascript objects. It's like a plug n play library and is easy to use. On the other hand, express-validator uses validator. js to validate expressjs routes, and it's mainly built for express.


2 Answers

You can use Joi's context option while calling validate method. something like

var Joi = require("@hapi/joi");

const schema = Joi.when(Joi.ref("$method"), {
          "is": "put",
          "then": Joi.object().keys({
            "id": Joi.string().required(),
            "name": Joi.string()
          }),
          "otherwise": Joi.object().keys({
            "id": Joi.string().forbidden(),
            "name": Joi.string()
          })
        });

function validate() {
    const result = schema.validate({"id": "123", "name": "myname"}, {"context": {"method": "put"}});
    console.log(result);
}

validate();

if you pass method as put, it will use put schema else post schema.

like image 177
Ashish Modi Avatar answered Nov 14 '22 21:11

Ashish Modi


On the project, we still use 14.3.1 version of joi. I could solve my problem with creating a base joi object and extending it like;

const base = joi.object().keys({name: joi.string()});
const put = base.keys({
    id: joi.string().required(),
});
const post = base.keys({
    id: joi.string().forbidden(),
});

Even it looks cleaner to read. I leave that here for if someone needs something similar.

like image 27
atasoyh Avatar answered Nov 14 '22 22:11

atasoyh