【问题标题】:Make sure an Object matches a data model确保对象与数据模型匹配
【发布时间】:2019-04-12 16:00:29
【问题描述】:

想象一下我有一个像这样的数据模型:

// Pseudo-code, as I don't know how to achieve this
const Model = {
    name: String.required,
    description: String.optional,
    rank: Number.required,
    // ...
}

基本上,这意味着对象必须具有属性name,并且它必须是String。属性description可选,但如果已定义,则必须是String。等等。

现在,假设我有一堆对象:

const obj1 = {
    name: 'Object 1',
    rank: 1,
}
const obj2 = {
    description: 'This is object 2',
    rank: 2,
}

为了将我的对象保存在 NoSQL 数据库(Firebase 的 Firestore)中,我想确保每个 Object 匹配 Model。例如,这将防止缺少字段。

在我的示例中,obj1 应该通过,但 obj2 不应该具有属性 name 丢失。

有没有办法在错误消息中抛出缺少哪些属性?

【问题讨论】:

  • 当然,例如 MongoDB 本身就支持这一点。快速搜索“JS 验证”会返回一些很好的库,这些库完全符合您的要求。
  • 模型是如何构建的?从表格?您应该在键值进入模型之前进行验证。

标签: javascript data-structures


【解决方案1】:

解决方案:

您可以创建一个简单的函数,该函数将根据一组必需和可选参数验证您的模型。

注意:下面有requiredoptional 参数硬编码在函数中,但您也可以通过很少的努力和代码更改来传递它们。只需删除声明并将它们作为参数添加到函数中。


代码

function validateModel(obj) {
  let
    // parameters specification
    required = ["name", "rank"],
    optional = ["description"],

    // helper methods
    toObjects = (a, v) => Reflect.has(obj, v) ? (a[v] = obj[v], a) : a,
    grab = (type) => type.reduce(toObjects, {}),
    payload = () => Object.assign(grab(required), grab(optional)),
    notValid = v => !Reflect.has(obj, v);

  //output
  if (required.some(notValid)) return false;
  return payload();
}

工作示例:

//setup
let log = (x) => { return console.log(x), log };
const Model={name:"n",description:"d",rank:"r"},Model2={rank:"a"},Model3={rank:"b",name:"b"};

// Validation Method:
function validateModel(obj) {
  let
    // parameters specification
    required = ["name", "rank"],
    optional = ["description"],

    // helper methods
    toObjects = (a, v) => Reflect.has(obj, v) ? (a[v] = obj[v], a) : a,
    grab = (type) => type.reduce(toObjects, {}),
    payload = () => Object.assign(grab(required), grab(optional)),
    notValid = v => !Reflect.has(obj, v);

  //output
  if (required.some(notValid)) return false;
  return payload();
}


// Examples:
log
  (validateModel(Model) || "Invalid Model")
  (validateModel(Model2) || "Invalid Model")
  (validateModel(Model3) || "Invalid Model")

多用途:

如果您创建模型检查器之类的东西,最好能够使用它检查多种类型的模型。下面的代码创建了一个构造函数,它接受一个充满结构的对象。每个 Struct 都包含一个 requiredoptional 参数数组。

ModelChecker 构造函数返回一个具有单一方法的对象,validate。通过传入要检查的对象和要检查的模型结构的名称,您可以确定模型是否有效。


工作示例:

//setup
let log = (x) => { return console.log(x), log };
const Model={name:"n",description:"d",rank:"r"},Model2={rank:"a"},Model3={rank:"b",name:"b"}, Car={"color":"black", "name": "toyota" }, Car2={"name":"chevy"};

//setup validation structures
const structs = {
  "identity": {
    required: ["name", "rank"],
    optional: ["description"]
  },
  "car": {
    required: ["color"],
    optional: ["name"]
  }
}

// model checker constructor
function ModelChecker(structs) {
  let proto = {
    structs
  };
  
  proto.validate = function validateModel(obj, struct) {
    if (!this.structs[struct]) return false;

    let
      // parameters specification
      required = this.structs[struct].required,
      optional = this.structs[struct].optional,

      // helper methods
      toObjects = (a, v) => Reflect.has(obj, v) ? (a[v] = obj[v], a) : a,
      grab = (type) => type.reduce(toObjects, {}),
      payload = () => Object.assign(grab(required), grab(optional)),
      notValid = v => !Reflect.has(obj, v);

    //output
    if (required.some(notValid)) return false;
    return payload();
  }

  return proto;
}

// Examples:

let mc = ModelChecker(structs);
log
  (mc.validate(Model, "identity") || "Invalid Model")
  (mc.validate(Model2, "identity") || "Invalid Model")
  (mc.validate(Model3, "identity") || "Invalid Model")
  (mc.validate(Car, "car") || "Invalid Model")
  (mc.validate(Car2, "car") || "Invalid Model")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    相关资源
    最近更新 更多