簡體   English   中英

Joi.object() 和 Joi.object().keys() 有什么區別?

[英]What is the difference between Joi.object() and Joi.object().keys()?

根據 Joi 文檔,您可以像這樣使用Joi.object()

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

但是您也可以使用Joi.object().keys()編寫等效代碼,如下所示:

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

兩者有什么區別?

如果您編寫一次架構,則不需要使用.keys() 正如他們的文檔所說,向 object 添加更多行(鍵)時使用.keys()是“有用的”。

Joi.object().keys([schema]) notation

這與Joi.object([schema])基本相同,但是當您想要添加更多鍵時(例如多次調用keys() ),使用Joi.object().keys([schema])更有用。 如果只添加一組鍵,則可以跳過keys()方法,直接使用object()

有些人喜歡使用keys()來使代碼更明確(這只是樣式)。

取自: https://github.com/hapijs/joi/blob/v8.0.3/API.md#joiobjectkeysschema-notation


我還發現了這個:

使用 joi 的方法有很多。 hapi 文檔無法顯示所有內容。 僅在將密鑰添加到 object 時才建議調用 keys(),因為它會創建另一個模式

取自: https://github.com/hapijs/hapi/issues/2222

@hapi/joi 文檔對此不是很清楚(在 v17.1.0 中)。 生成的模式具有相同的值,並且它們驗證相同。 查看源代碼,Object 類型是 Keys 類型,只是 object 不需要從定義它的 Any 類型復制密鑰。

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: {} }

.append(schema).keys(schema)之間的區別在文檔中也不清楚。 如果 schema 為空, .append(schema)不會創建新副本,否則它只會返回.keys(schema)的值。 我沒有發現這會有所作為的例子。

> 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

如文檔所述:

object.keys([架構])

設置擴展允許的 object 鍵,其中:

  • schema - 可選 object,其中每個鍵都分配有一個 joi 類型 object。 如果架構是 {},則不允許使用任何鍵。 如果架構是 null 或未定義,則允許任何鍵。 如果 schema 是帶有鍵的 object,則將鍵添加到任何先前定義的鍵(但如果先前允許所有鍵,則縮小選擇范圍)。

因此,通過調用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()創建頂級模式,但最后我認為這是個人喜好問題。

當只有一組鍵直接在 object() 生成中定義我們的模式時,我們也可以在不使用 keys() 的情況下定義模式,如下所示:

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 模式測試的任何 object 無效。 我們還可以選擇在模式的原始定義之后添加鍵。 以下來自 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 對象是不可變的,因此擴展基本模式將產生全新的 object。 在這里,我們將 object 保存為常量擴展。 我們還介紹了上面的 Joi.boolean() 規則,它在測試復選框和其他開關時非常方便,我們需要一個真或假值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM