Javascript Joi.object()和Joi.object().keys()之间有什么区别?

Javascript Joi.object()和Joi.object().keys()之间有什么区别?,javascript,node.js,validation,joi,Javascript,Node.js,Validation,Joi,根据Joi文档,您可以像这样使用Joi.object(): const object = Joi.object({ a: Joi.number().min(1).max(10).integer(), b: Joi.any() }); const object = Joi.object().keys({ a: Joi.number().min(1).max(10).integer(), b: Joi.any() }); 但您也可以使用Joi.object().k

根据Joi文档,您可以像这样使用
Joi.object()

const object = Joi.object({
    a: Joi.number().min(1).max(10).integer(),
    b: Joi.any()
});
const object = Joi.object().keys({
    a: Joi.number().min(1).max(10).integer(),
    b: Joi.any()
});
但您也可以使用
Joi.object().keys()
编写等效代码,如下所示:

const object = Joi.object({
    a: Joi.number().min(1).max(10).integer(),
    b: Joi.any()
});
const object = Joi.object().keys({
    a: Joi.number().min(1).max(10).integer(),
    b: Joi.any()
});

这两者之间有什么区别?

当只有一组键时,我们也可以定义模式而不使用keys() 直接在object()生成中定义我们的模式,如下所示:

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');
那么为什么要将keys()与单个键集一起使用呢?

保持代码的一致性。在整个Joi文档中,keys()始终使用,即使是在单键对象上

使用键()

如前所述,如果定义单个键集,则不必使用keys()。此外,如果没有在Joi.object()上定义任何键,那么任何键都是有效的:没有规则使我们使用Joi模式测试的任何对象无效。 我们还可以选择在模式的原始定义之后添加键。以下摘自Joi文档的示例演示了这一点:

//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()
});
正如您可能已经注意到的,我们在这里定义常量。Joi对象是不可变的,因此扩展基本模式将产生一个全新的对象。在这里,我们将该对象保存为常量扩展。 我们还引入了上面的Joi.boolean()规则,该规则对于测试复选框和其他开关非常方便,因为在这些开关中,我们需要一个真值或假值。

关于这一点(在v17.1.0中)还不是很清楚。结果模式具有相同的值,并且它们验证相同的值。从源代码上看,对象类型是一种键类型,只有一个更改,对象不需要从定义它的任何类型复制键

欢迎使用Node.js v12.16.1。
键入“.help”以获取更多信息。
>const Joi=require(“@hapi/Joi”)
未定义
>const util=require('util')
未定义
>常量object1=Joi.object({
…a:Joi.number().min(1).max(10).integer(),
…b:Joi.any()
... });
未定义
>const object2=Joi.object().keys({
…a:Joi.number().min(1).max(10).integer(),
…b:Joi.any()
... });
未定义
>util.format(object1)==util.format(object2)
真的
>object1.validate({a:1,b:1})
{值:{a:1,b:1}
>object2.validate({a:1,b:1})
{值:{a:1,b:1}
>object1.validate({a:0})
{
值:{a:0},
错误:[错误[ValidationError]:“a”必须大于或等于1]{
_原件:{a:0},
详细信息:[[对象]]
}
}
>object2.validate({a:0})
{
值:{a:0},
错误:[错误[ValidationError]:“a”必须大于或等于1]{
_原件:{a:0},
详细信息:[[对象]]
}
}
>object1.validate({a:1,b:1,c:1})
{
值:{a:1,b:1,c:1},
错误:[错误[ValidationError]:“c”是不允许的]{
_原件:{a:1,b:1,c:1},
详细信息:[[对象]]
}
}
>object2.validate({a:1,b:1,c:1})
{
值:{a:1,b:1,c:1},
错误:[错误[ValidationError]:“c”是不允许的]{
_原件:{a:1,b:1,c:1},
详细信息:[[对象]]
}
}
>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({})
{值:{}
>object2.validate({})
{值:{}
文档中也不清楚
.append(schema)
.keys(schema)
之间的区别。如果架构为空,则
.append(schema)
不会创建新副本,否则它只返回
.keys(schema)
中的值。我没有发现这会有什么不同的例子

>util.format(Joi.object({}).keys({a:1}))==util.format(Joi.object({}).append({a:1}))
真的
>util.format(Joi.object({}).unknown().keys({a:1}))==util.format(Joi.object({}).unknown().append({a:1}))
真的

如果只编写一次模式,则不需要使用
.keys()
。正如他们的文档所说,在向对象添加更多行(键)时,使用
.keys()
是“有用的”

Joi.object().keys([schema])表示法

这与
Joi.object([schema])
基本相同,但是当您想要添加更多键时(例如多次调用
keys()
),使用
Joi.object().keys([schema])
更有用。如果只添加一组键,可以跳过
keys()
方法,直接使用
object()

有些人喜欢使用
keys()
使代码更加明确(这只是样式)

摘自:


我还发现:

使用joi的方法有很多。hapi文档不能显示所有内容。只有在对象创建另一个架构时向对象添加键时,才建议调用keys()


摘自:

如文档所述:

object.keys([schema])

设置或扩展允许的对象关键帧,其中:

  • 模式-可选对象,其中每个关键点都分配有一个joi类型的对象。如果架构为{},则不允许使用键。如果架构为null或未定义,则允许使用任何键如果架构是具有键的对象,则键将添加到任何先前定义的键(但如果先前允许所有键,则缩小选择范围)
因此,通过调用
Joi.object()
首先创建一个允许任何键的模式,然后通过调用
.keys([schema])
扩展该模式(基本上与使用
Joi.object([schema])
定义新模式相同)

所以这两个是等价的:

const a = Joi.object({ firstName: Joi.string() });
const b = Joi.object().keys({ firstName: Joi.string() });
您还可以扩展上面创建的两个架构:

const aExtended = a.keys({ lastName: Joi.string() })
const bExtended = b.keys({ lastName: Joi.string() })
那用哪一个呢?
正如前面的回答中所述,出于代码一致性的原因,有时也会使用
.keys()
创建顶级模式,但最终我认为这是个人偏好的问题。

两者并不等同。第一个示例定义了一个只允许<代码的模式