admin管理员组文章数量:1178538
According to Joi documentation, you can use Joi.object()
like so:
const object = Joi.object({
a: Joi.number().min(1).max(10).integer(),
b: Joi.any()
});
But you can also write an equivalent code using Joi.object().keys()
like so:
const object = Joi.object().keys({
a: Joi.number().min(1).max(10).integer(),
b: Joi.any()
});
What's the difference between the two?
According to Joi documentation, you can use Joi.object()
like so:
const object = Joi.object({
a: Joi.number().min(1).max(10).integer(),
b: Joi.any()
});
But you can also write an equivalent code using Joi.object().keys()
like so:
const object = Joi.object().keys({
a: Joi.number().min(1).max(10).integer(),
b: Joi.any()
});
What's the difference between the two?
Share Improve this question asked Nov 12, 2019 at 3:17 BerryBerry 2,2985 gold badges26 silver badges49 bronze badges 1 |4 Answers
Reset to default 14If you're writing your schema once then you do not need to use .keys()
. As their docs say it is "useful" to use .keys()
when added more lines (keys) to your object.
Joi.object().keys([schema]) notation
This is basically the same as
Joi.object([schema])
, but usingJoi.object().keys([schema])
is more useful when you want to add more keys (e.g. callkeys()
multiple times). If you are only adding one set of keys, you can skip thekeys()
method and just useobject()
directly.Some people like to use
keys()
to make the code more explicit (this is style only).
Taken from: https://github.com/hapijs/joi/blob/v8.0.3/API.md#joiobjectkeysschema-notation
I also found this:
There are many ways to use joi. The hapi docs can't show everything. Calling keys() is only recommended when adding keys to an object as it creates another schema
Taken from: https://github.com/hapijs/hapi/issues/2222
Like the documentation states:
object.keys([schema])
Sets OR extends the allowed object keys where:
- schema - optional object where each key is assigned a joi type object. If schema is {} no keys allowed. If schema is null or undefined, any key allowed. If schema is an object with keys, the keys are added to any previously defined keys (but narrows the selection if all keys previously allowed).
Thus by calling Joi.object()
you first create a schema that allows any keys and then by calling .keys([schema])
you extend that schema (basically the same as defining a new schema with Joi.object([schema])
)
So these two are equivalent:
const a = Joi.object({ firstName: Joi.string() });
const b = Joi.object().keys({ firstName: Joi.string() });
You can also extend both schemas created above:
const aExtended = a.keys({ lastName: Joi.string() })
const bExtended = b.keys({ lastName: Joi.string() })
Which one to use then?
Like stated in the previous answers, sometimes also top level schemas are created using .keys()
for code consistency reasons, but in the end I think it's a matter of personal preference.
The @hapi/joi documentation is not very clear on this (at v17.1.0). The resulting schemas have the same value, and they validate the same. Looking at the source, Object type is a Keys type with only a change that object need not copy keys from the Any type it is defined from.
Welcome to Node.js v12.16.1.
Type ".help" for more information.
> const Joi = require('@hapi/joi')
undefined
> const util = require('util')
undefined
> const object1 = Joi.object({
... a: Joi.number().min(1).max(10).integer(),
... b: Joi.any()
... });
undefined
> const object2 = Joi.object().keys({
... a: Joi.number().min(1).max(10).integer(),
... b: Joi.any()
... });
undefined
> util.format(object1) == util.format(object2)
true
> object1.validate({a: 1, b: 1})
{ value: { a: 1, b: 1 } }
> object2.validate({a: 1, b: 1})
{ value: { a: 1, b: 1 } }
> object1.validate({a: 0})
{
value: { a: 0 },
error: [Error [ValidationError]: "a" must be larger than or equal to 1] {
_original: { a: 0 },
details: [ [Object] ]
}
}
> object2.validate({a: 0})
{
value: { a: 0 },
error: [Error [ValidationError]: "a" must be larger than or equal to 1] {
_original: { a: 0 },
details: [ [Object] ]
}
}
> object1.validate({a: 1, b: 1, c:1})
{
value: { a: 1, b: 1, c: 1 },
error: [Error [ValidationError]: "c" is not allowed] {
_original: { a: 1, b: 1, c: 1 },
details: [ [Object] ]
}
}
> object2.validate({a: 1, b: 1, c:1})
{
value: { a: 1, b: 1, c: 1 },
error: [Error [ValidationError]: "c" is not allowed] {
_original: { a: 1, b: 1, c: 1 },
details: [ [Object] ]
}
}
> object1.validate({a: 1})
{ value: { a: 1 } }
> object2.validate({a: 1})
{ value: { a: 1 } }
> object1.validate({b: 1})
{ value: { b: 1 } }
> object2.validate({b: 1})
{ value: { b: 1 } }
> object1.validate({})
{ value: {} }
> object2.validate({})
{ value: {} }
Difference between the .append(schema)
and .keys(schema)
is also unclear in documentation. The .append(schema)
does not create a new copy if schema is empty, but otherwise it just returns the value from .keys(schema)
. I found no example where this would make a difference.
> util.format(Joi.object({}).keys({a:1})) == util.format(Joi.object({}).append({a:1}))
true
> util.format(Joi.object({}).unknown().keys({a:1})) == util.format(Joi.object({}).unknown().append({a:1}))
true
We can also define schema without using keys() when there is only one set of keys define our schema directly within the object() generation, like so:
const schema = Joi.object({
username: Joi.string().alphanum().min(3).max(16).required(),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/).min(6).required()
}).with('username', 'password');
So why use keys() with a single key set?
To keep your code consistent. Throughout the Joi documentation keys() are used throughout, even on single key objects.
Using keys()
As we mentioned before, keys() does not have to be used if we are defining a single key set. Additionally, if no keys are defined on a Joi.object(), then any key will be valid: there are no rules to invalidate any object we test with our Joi schema. We also have the option to add keys after the schema’s original definition. The following example taken from the Joi documentation demonstrates this:
//define base object
const base = Joi.object().keys({
a: Joi.number(),
b: Joi.string()
});
// add a c key onto base schema
const extended = base.keys({
c: Joi.boolean()
});
As you may have noticed, we are defining constants here. Joi objects are immutable, so extending a base schema will result in a completely new object. Here we have saved that object as the constant extended. We have also introduced the Joi.boolean() rule above, which comes in handy for testing checkboxes and other switches, where we expect a true or false value.
本文标签: javascriptWhat is the difference between Joiobject() and Joiobject()keys()Stack Overflow
版权声明:本文标题:javascript - What is the difference between Joi.object() and Joi.object().keys()? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738083658a2060837.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
a
andb
. The second example withobject()
usesJoi.any()
as the initial schema and then extends it by adding definitions fora
andb
while presumably inheritingany
's permissive schema definition. You probably don't want to extendany
unless you know you're handling open-ended input. – Dai Commented Nov 12, 2019 at 3:25