【问题标题】:How to validate deeply nested object structure如何验证深度嵌套的对象结构
【发布时间】:2019-11-01 10:08:19
【问题描述】:

我已经定义了具有嵌套属性的对象。我想创建一个验证器函数,它将检查另一个对象是否具有与我定义的对象相同的结构和值类型!

是对象的定义:

const OBJECT_SCHEMA = {
  name: String,
  data: [{
    isSelected: Boolean,
    mId: String,
    mSummary: String,
    mMarkets: Array,
    mBdd: String,
    mReplaceDict: Object,
    omId: String,
    omnSummary: String,
    omnMarkets: Array,
    omnBdd: String,
    omnReplaceDict: {
      id: String,
      text: String,
    },
  }],
  metadata: {
    emails: Array,
    description: String,
  },
};

这是我用于验证的功能。目前它只适用于一个嵌套级别!我希望它可以通过许多嵌套级别进行验证。

function validateObjectStructure(schema, obj) {
  let valid = true;
  firstLevel: for(const k in schema) {
    if(schema[k].constructor === Array) { // if prop is of type array
      let i;
      for(i = 0; i < schema[k].length; i++) {
        for(const kk in schema[k][i]) {
          if(!obj[k][i].hasOwnProperty(kk) || obj[k][i][kk].constructor !== schema[k][i][kk]) {
            valid = false;
            break firstLevel;
          }
        }
      }
    }
    else if(schema[k].constructor === Object) { // if prop is of type object
      for(const kk in schema[k]) {
        if(!obj[k].hasOwnProperty(kk) || obj[k][kk].constructor !== schema[k][kk]) {
          valid = false;
          break firstLevel;
        }
      }
    }
    else { // if prop is simple type
      if(!obj.hasOwnProperty(k) || obj[k].constructor !== schema[k]) {
        valid = false;
        break;
      }
    }
  }
  return valid;
}

【问题讨论】:

  • 你需要递归。

标签: javascript


【解决方案1】:

您需要使用obj 的嵌套级别吗?如果是,您可以这样做而不是最后一行:

Object.values(obj).reduce((accValid, value) => {
  if (typeof value === 'object') {
    return accValid && validateObjectStructure(schema, value);
  }
  return accValid;
}, valid);

return valid;

【讨论】:

    【解决方案2】:

    这是一个可能的实现:

    function validate(obj, schema, path = '') {
        let ok = true;
    
        if (!obj)
            ok = obj === schema;
        else if (typeof schema === 'function')
            ok = obj.constructor === schema;
        else if (typeof obj !== 'object')
            ok = obj === schema;
        else if (Array.isArray(schema))
            ok = Array.isArray(obj) && obj.every((x, k) => validate(x, schema[0], path + '[' + k + ']'));
        else {
            let ko = Object.keys(obj);
            let ks = Object.keys(schema);
            ok = ko.length === ks.length && ks.every(k => validate(obj[k], schema[k], path + '.' + k));
        }
        if (!ok)
            throw new Error('FAILED ' + path);
        return true;
    }
    
    // example:
    
    
    const OBJECT_SCHEMA = {
        name: String,
        data: [{
            isSelected: Boolean,
            mId: String,
            omnReplaceDict: {
                id: String,
                text: {
                    deepObj: {
                        deepProp: [Number]
                    }
    
                },
            },
        }],
    };
    
    const obj = {
        name: "foo",
        data: [{
            isSelected: true,
            mId: "bar",
            omnReplaceDict: {
                id: "foo",
                text: {
                    deepObj: {
                        deepProp: [1, 2, "???", 3]
                    }
    
                },
            },
        }]
    };
    
    
    validate(obj, OBJECT_SCHEMA)

    注意:尽管这个自制的类型检查器似乎可以正常工作,但它非常有限(例如,如何表达“字符串-数字对数组”或“null 或某个对象”?),所以它可能是一个选项雇用一个真正的人,比如 Typescript。请参阅here 了解可能的实现。

    【讨论】:

      猜你喜欢
      • 2019-03-15
      • 1970-01-01
      • 2021-07-18
      • 2020-12-18
      • 1970-01-01
      • 2021-07-14
      • 2021-04-12
      • 2017-08-27
      • 2021-08-31
      相关资源
      最近更新 更多