【问题标题】:How to validate object based on computed value using Joi?如何使用 Joi 根据计算值验证对象?
【发布时间】:2020-03-14 23:33:48
【问题描述】:

我在 wgich 中有一个对象,我想用一些计算值来验证它的值。现在我正在使用 javascript 方式进行操作,但我想使用 Joi 来进行操作。

{
    "scoreThreshold": 1,
    "questions": [
      {
        "question": "someString",
        "answer": 1,
        "factor": 2
      },
      {
        "question": "someString"
        "answer": 3
      },
      {
        "question": "someString",
        "answer": 0,
        "factor": 3
      },
      {
        "question": "someString"
        "answer": 1
      }
    ],
  }

我正在使用 javascript 验证它

var validator = function(doc) {
    var maxScore = 0
    for (var item of doc.questions) {
        maxScore += 1000 * (item.factor == undefined ? 1: item.factor)
    }

    if (maxScore == 0) {
        throw new Error("maxScore is 0")
    }

    if (doc.scoreThreshold > maxScore) {
        throw new Error("scoreThreshold more than maxScore")
    } else if ((doc.scoreThreshold / maxScore) > 0.95) {
        throw new Error("scoreThreshold too close to maxScore")
    }
}

如何以Joi 方式进行此验证?

【问题讨论】:

    标签: javascript node.js validation object joi


    【解决方案1】:

    我们可以使用Joi.ref()adjust 选项以Joi 方式执行此操作

    var calculateMaxScore = function(questions) {
        return (questions || []).reduce((t, e) => t + 1000 * (e.factor == undefined ? 1: e.factor), 0)
    }
    
    var schema = Joi.object({
        "scoreThreshold": Joi.number().integer()
            .greater(0)
            .less(Joi.ref('questions', { adjust: (v) => calculateMaxScore(v) * 0.95 }))
            .required(),    
        "questions": Joi.array().items(Joi.object({
            "question": JJoi.string().min(1)).required(),
            "answer": Joi.number().integer().min(0).required(),
            "factor": Joi.number().integer().min(0)
        }))
        .required()
    })
    

    【讨论】:

      【解决方案2】:

      您可以使用any.custom() 进行自定义验证

      any.custom(method, [description])

      var schema = Joi.object()
        .keys({
          scoreThreshold: Joi.number(),
          questions: Joi.array().items(
            Joi.object({
              question: Joi.string(),
              answer: Joi.number(),
              factor: Joi.number()
            })
          )
        })
        .custom((doc, helpers) => {
          var maxScore = 0;
          for (var item of doc.questions) {
            maxScore += 1000 * (item.factor == undefined ? 1 : item.factor);
          }
      
          if (maxScore == 0) {
            throw new Error("maxScore is 0");
          }
      
          if (doc.scoreThreshold > maxScore) {
            throw new Error("scoreThreshold more than maxScore");
          } else if (doc.scoreThreshold / maxScore > 0.95) {
            throw new Error("scoreThreshold too close to maxScore");
          }
      
          // Return the value unchanged
          return doc;
        });
      

      stackblitz

      【讨论】:

      • 这不是 Joi 方式。当我没有得到任何谷歌解决方案时,我会使用 any.custom。
      • @AlokSinghMahor 这对我来说看起来不错。不知道你所说的“Joi way”是什么意思。
      • @MarkMcKelvy:查看 Joi 方式的其他分析器
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 2017-08-05
      • 1970-01-01
      • 2019-01-20
      • 2019-12-13
      • 2018-02-27
      • 2021-06-26
      相关资源
      最近更新 更多