簡體   English   中英

驗證 Joi - 所有數組元素都具有相同的嵌套值

[英]Validate Joi - all array elements have the same nested value

我想使用 Joi 來驗證傳入的 JSON 請求對象,以便每個數組元素在路徑.runs[].results.type處具有相同的值。 如果有一個元素突出,則驗證應該失敗。 類似於.runs[]內的array.unique上的.results.type .runs[]

將以下 JSON 想象為有效輸入:

{
  runs: [
    { results: { type: 'A', side: 'left' }, meta: { createdBy: 3 } },
    { results: { type: 'A', side: 'right' }, meta: { createdBy: 1 } }
  ]
}

這應該會引發驗證錯誤:

{
  runs: [
    { results: { type: 'A', side: 'left' }, meta: { createdBy: 3 } },
    { results: { type: 'B', side: 'right' }, meta: { createdBy: 1 } }
  ]
}

我嘗試編寫一個 Joi 模式,如:

...
  runs: Joi.array()
    .min(1)
    .items(
      Joi.object()
        .unknown()
        .keys({
          results: Joi.object()
            .keys({
              type: Joi.string()
                .allow('A', 'B', 'C', 'D')
                .valid(Joi.ref('....', { in: true, adjust: runs => runs.map(run => run.results.type) }))
                .required(),
              side: Joi.string().allow('left', 'right')
            })
        })
    )
...

但這不起作用(我認為它以循環引用結束)。 此外,即使它成功運行,我也不確定它是否會在提供兩種差異類型AB情況下破壞驗證。

我想我找到了一種不使用自定義函數的優雅解決方案,盡管這將是解決這個問題的一個很好的方法!

Joi.object().keys({
  runs: Joi.array().items(
    Joi.object().keys({
      results: Joi.object().keys({
        type: Joi.string().valid(
          Joi.ref('....0.results.type')
        ).required() 
      })
    })
  ).has(
    Joi.object().keys({ 
      results: Joi.object().keys({
        type: Joi.valid('A', 'B', 'C', 'D').required()
      })
    }))
  })

它基於首先確定所有runs[]元素具有相同的.results.type值,然后斷言runs數組.has()至少一個元素具有來自{'A', 'B', 'C', 'D'} .results.type {'A', 'B', 'C', 'D'}

我學到的有趣的事情是,在 Joi 中,數組元素在.ref()中用點索引,例如$runs.0.results

您需要使用.some() o .every()函數,如果至少有某個元素完成某個條件,或者每個元素都完成一個條件,則該函數返回:

1)使用.some()

 const object1 = { runs: [ { results: { type: 'A', side: 'left' }, meta: { createdBy: 3 } }, { results: { type: 'A', side: 'right' }, meta: { createdBy: 1 } } ]}; const object2 = { runs: [ { results: { type: 'A', side: 'left' }, meta: { createdBy: 3 } }, { results: { type: 'B', side: 'right' }, meta: { createdBy: 1 } } ]}; let result1 = object1.runs.some(e => e.results.type !== 'A'); console.log(result1); // false let result2 = object2.runs.some(e => e.results.type !== 'A'); console.log(result2); // true

2)使用.every()

 const object1 = { runs: [ { results: { type: 'A', side: 'left' }, meta: { createdBy: 3 } }, { results: { type: 'A', side: 'right' }, meta: { createdBy: 1 } } ]}; const object2 = { runs: [ { results: { type: 'A', side: 'left' }, meta: { createdBy: 3 } }, { results: { type: 'B', side: 'right' }, meta: { createdBy: 1 } } ]}; let result1 = object1.runs.every(e => e.results.type === 'A'); console.log(result1); // true let result2 = object2.runs.every(e => e.results.type === 'A'); console.log(result2); // false

  • 如果您不知道目標值(在本例中為'A' ),只需取第一個類型值 -> runs[0].results.type並用它替換 'A' 。

暫無
暫無

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

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