【问题标题】:What is the most lightweight way to check that a JSON object conforms to an expected schema?检查 JSON 对象是否符合预期模式的最轻量级方法是什么?
【发布时间】:2019-11-26 19:11:54
【问题描述】:

这似乎是一种常见的乏味模式:

function handleResponse(httpResponseBody) {
  const body = JSON.parse(httpResponseBody);
  if (body.someField &&
      body.someField.length >= 5 &&
      body.someField[4].otherField &&
      body.someField[4].otherField.finalField) {
    /* ... do something with finalField ... */
  }
}

有点做作,但重点是如何避免像这样的样板验证逻辑,如果您只是要通过手术访问对象的某些部分并希望最小化验证该部分,则无需对主体进行完整的 JSON 模式验证结构是否符合预期?轻量级的东西,概念上很简单:

function handleResponse(httpResponseBody) {
  const body = JSON.parse(httpResponseBody);
  if (validate(body, '{ someField[>=5].otherField.finalField }') {
    /* ... safe to access body.someField[4].otherField.finalField directly ... */
  }
}

或者可能:

function handleResponse(httpResponseBody) {
  const body = JSON.parse(httpResponseBody);
  const finalField = access(body, '{ someField[4].otherField.finalField }');
  if (finalField) {
    /* ... */
  }
}

【问题讨论】:

  • 完整的 JSON 模式似乎比我想要的要重一些,但我发现它有更简单的使用场景。但可能这里的一些答案中提出的 try/catch 方法仍然更简单。

标签: javascript json jsonschema


【解决方案1】:

最简单的方法是将它简单地包装在一个 try/catch 块中:

var data = {body: { someField: [0,0,0,0, { otherField: { finalField: 'test'}}]}};
try {
   var finalField = data.body.someField[4].otherField.finalField;
   console.log(finalField);
} catch(e) {
   console.error('Invalid');
}

try {
   var finalField = data.body.someField[7].otherField.finalField;
   console.log(finalField);
} catch(e) {
   console.error('Invalid');
}

您也可以通过 try/catch 块再次使用 ES6 destructuring

try {
  var { body: { someField: [,,,,{ otherField: { finalField }}] }} = {body: { someField: [0,0,0,0, { otherField: { finalField: 'test'}}]}};

  console.log(finalField);
} catch(e) {
  console.error('Invalid');
}

try {
  var { body: { someField: [,,,,{ otherField: { finalField }}] }} = {body: { someField: [0,0,0, { otherField: { finalField: 'test'}}]}};
  console.log(finalField);
} catch (e) {
  console.error('Invalid');
}

如果你想使用点路径(例如"body.someField.4.otherField.finalField",你可以这样做:

var data = {body: { someField: [0,0,0,0, { otherField: { finalField: 'test'}}]}};
var finalField = 'body.someField.4.otherField.finalField'.split('.').reduce((o,i)=>o[i], data);
console.log(finalField);
try {
finalField = 'body.someField.7.otherField.finalField'.split('.').reduce((o,i)=> o[i], data);
console.log(finalField);
} catch(e) {
    console.error('Invalid');
}

【讨论】:

    【解决方案2】:

    我不知道你的设计是什么,但如果这是对象的预期格式,只需将你的逻辑放在 try catch 块中。

    【讨论】:

      【解决方案3】:

      为子孙后代解答。基于https://github.com/tc39/proposal-optional-chaining,可在当前的 TypeScript 和 Babel 插件中使用。

      你可以使用可选链。

      const finalField = body.someField?.[4]?.otherField?.finalField;
      
      if (finalField) {
          /* ... do something with finalField ... */
      }
      

      【讨论】:

        猜你喜欢
        • 2016-02-08
        • 2011-03-27
        • 2011-03-20
        • 2016-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-15
        • 2010-11-30
        相关资源
        最近更新 更多