【问题标题】:Sails JS: Validating model with embedded JSON propertySails JS:使用嵌入式 JSON 属性验证模型
【发布时间】:2019-07-20 18:19:23
【问题描述】:

如何在 Sails JS 中验证具有对象类型属性的模型?

我知道具有简单值(例如字符串)的属性是可以接受的,但是这对于嵌套的 JSON 有什么作用?

如下:

{
    name: 'John',
    location: {
        x: 23,
        y: 15,
        z: 50
    }
}

它会是这样的形式:

{
    name: {
        type: 'string',
        required: true,
    },
    location: {
        x: {
            type: 'number',
            required: true
        },
        y: {
            type: 'number',
            required: true
        },
        z: {
            type: 'number',
            required: true
        }
    }
}

【问题讨论】:

    标签: javascript sails.js


    【解决方案1】:

    Waterline(Sails ORM)不直接支持嵌套模式。您可以改用custom validation rule 来验证属性:

    module.exports = {
    
      types: {
        location: function(val) {
          // Make sure that x, y and z are present and are numbers.
          // This won't allow numeric strings, but you can adjust to fit your needs.
          return (_.isNumber(val.x) && _.isNumber(val.y) && _.isNumber(val.z));
        }
      },
    
      attributes: {
    
        location: {
          type: 'json',
          required: true, // If you want the whole attribute to be required
          location: true  // Validate that the attribute has the schema you want
        }
    
        ...more attributes...
    
      }
    
    };
    

    【讨论】:

    • 我想使用像waterlineSchema: true 这样的验证规则来使用所有支持的类型和来自sails/waterline 的验证。有什么提示吗?库?
    【解决方案2】:

    到目前为止,我发现的最优雅的解决方案是使用“机器”库(它为sailsjs 中的动作提供动力,由sailsjs 人构建)来定义类型验证“机器”。

    首先你需要一个类型定义助手:

    $ cat api/types/define.js 
    const buildWithCustomUsage = require("machine").buildWithCustomUsage;
    
    function validateWith(machine, inputs) {
        machine(inputs).now();
        return true;
    }
    
    module.exports = function (def) {
        const machine = buildWithCustomUsage({
            def,
            extraArginsTactic: "doNotCheck"
        });
        return {
            machine,
            validate: validateWith.bind(null, machine)
        };
    };
    

    然后你可以定义一个这样的类型:

    $ cat api/types/QuoteRequest.js 
    module.exports = require("./define")({
    
        description: "Quote request type definition",
    
        inputs: {
            input_currency_type: {
                description: "Input currency type",
                type: "string",
                required: true
            },
            amount_requested: {
                description: "Requested amount in input currency",
                type: "string",
                required: true
            }
        },
    
        sync: true,
    
        fn: function (inputs, exits) {
            // your other validation logics
            return exits.success();
        }
    });
    

    您需要确保设置了sync: true

    要在您的控制器中使用它,请执行以下操作:

    inputs: {
        request: {
            type: "json",
            required: true,
            custom: require("../../types/QuoteRequest").validate
        }
    },
    

    希望对你有帮助!

    【讨论】:

      【解决方案3】:

      我做了一个结构比较函数来处理这样的情况,分享给大家,希望对大家有所启发和帮助:

      假设您使用的是sails v1

      ./api/services 中创建一个名为ModelService.js 的文件,代码如下:

      module.exports = {
        invalidStructure(schema, input) {
          try {
            if (schema.type === 'array') {
              // Invalid: if input is not array
              //  OR some of input[items] doesn't match schema.item
              return !_.isArray(input) ||
                _.some(input, item => this.invalidStructure(schema.item, item));
            }
            else if (schema.type === 'object') {
              // Invalid if input is not an object
              //  OR if input.keys doesn't match schema.struct.keys
              //  OR if typeof input[key] doesn't match schema.struct[key]
              return !_.isObjectLike(input) ||
                !_.isEqual(_.keys(schema.struct), _.keys(input)) ||
                _.some(_.keys(input), key => this.invalidStructure(schema.struct[key], input[key]));
            }
            else { // verifying field value vs schema.type
              // TODO: Add other field validations here (i.e. isEmail, required,...etc.)
              return typeof input !== schema.type;
            }
          }
          catch (err) {
            sails.log.error('Exception in [invalidStructure] : ', err);
            return true;
          }
        }
      }
      

      并在您的模型中像这样使用它:

      const address = {
        type: 'object',
        struct: {
          name: { type: 'string' },
          location: {
            type: 'object',
            struct: {
              x: { type: 'string' },
              y: { type: 'string' },
              z: { type: 'string' },
            }
          }
        }
      }
      module.exports = {
        attributes: {
          address: {
            type: 'json',
            custom: value => !ModelService.invalidStructure(address, value)
          }
        }
      }
      

      现在我知道这不处理或情况(即required: false

      但它应该让你去匹配json结构值类型

      注意:这是source file。随意使用,或通过 PR 增强

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-29
        • 2015-07-18
        • 2019-09-14
        相关资源
        最近更新 更多