【问题标题】:JSON schema conditional check on certain object attribute within an array对数组中的某些对象属性进行 JSON 模式条件检查
【发布时间】:2019-09-27 13:38:04
【问题描述】:

我想通过 AJV 执行的操作 - JSON 模式验证或自定义关键字(最好我会这样做):数组可以有 1 或 2 个 JSON 对象,类型为“admin”和“guest”。 "type":"guest" 对象将始终存在,并且 "type":"admin" 对象是可选的。

补充说明:

-对象本身将来可能包含附加属性和嵌套对象

-其他有效的枚举是superadmin、admin、user和guest

-数组中的类型顺序为:superadmin、admin、user和guest。是否可以检查顺序? (尽管它是可选的)

-'guest' 类型的对象将始终存在,并且会有一个唯一类型的对象。如果再次出现任何对象类型(例如超级管理员、管理员、用户和访客),那么它就是一个错误

//这里是架构:

{
"type": "object",
"properties": {
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "type": { "enum": ["guest", "admin"]
    },
    "rights": {"type": "string"},
    "hyperLink": {"type": "string", "format": "uri"}
    }
  }
  }
}

我需要在 json 中的某处添加 'checkTypeAndValue' 标志,以便我可以获取完整的 JSON 对象和相应的属性来进行编程检查?

const checkTypeAndValue = function (schema, completeJSONObj) {
 //
};

ajv.addKeyword('checkTypeAndValue', {
  validate: checkTypeAndValue,
  errors: true
});

这里有一些有效和无效的例子:

/Valid 1: As type is 'admin' and so 'rights' SHOULD NOT be in 'guest' object
{
  [
    {
      "type":"admin",
      "hyperLink": "http://www.someguest.com",
      "rights":"all"
    },
    {
      "type":"guest",
      "hyperLink": "http://www.someadmin.com"
    }
  ]
}

//Valid 2: You can have a SINGLE 'guest' object. 'admin' object is not required all the time
{
  [
    {
      "type":"guest",
      "hyperLink": "http://www.someadmin.com",
      "rights": "limited" //MANDATORY or REQUIRED Attribute
    }
  ]
}

//InValid
{
  [
    {
      "type":"admin",
      "hyperLink": "http://www.someguest.com",
      "rights":"all"
    },
    {
      "type":"guest",
      "hyperLink": "http://www.someadmin.com",
      "rights":"limited"
      //Error ==> As rights=all is there in 1st object, you cannot set 'rights' to any value including blank even having 'rights' attribute is not valid.
    }
  ]
}

这是我需要整理的 if else 条件:

//Assuming admin object exist with rights....
if( type == admin && rights != ""){
  if(type == guest && rights attribute is there && rights != ""){
    //The 'guest' object will always be there....
    //error: guest 'rights' cannot have a value if type is 'admin' and rights is 'all' or any other value.
  }
}else{
   //Assuming mandatory guest object exist with rights....
   if(guest.rights does not exist OR guest.rights == "")
    //Error: 'rights' is MANDATORY attribute in guest block and error if its empty
   else 
    //Everything is fine
}

还有什么方法可以让我们在数组中检查是否只有一对特定类型的对象? 例如:只有一种 'guest、'admin' 类型。错误,如果有不止一种类型的 'guest' 或 'admin'

//完整示例

{
  [
    {
      "type":"superadmin",
      "hyperLink": "http://www.superadmin.com"      
    },
    {
      "type":"admin",
      "hyperLink": "http://www.admin.com",
      "rights":"all"
    },
    {
      "type":"user",
      "hyperLink": "http://www.user.com"
    },
    {
      "type":"guest",
      "hyperLink": "http://www.guest.com"
    }
  ]
}

【问题讨论】:

  • 我认为仅使用纯 JSON Schema 就可以做到这一点。只是为了澄清,您的数组是否只有两个对象,或者它们可能有超过 2 个?顺序是已知的还是未知的(不是问题,但解决方案可能不同)?
  • 其实没什么区别。为您找到解决方案。
  • 数组可以有更多的对象作为更新的问题。如果我们能管理订单就好了。正如您所提到的,这可能很棘手,这是否是 ajv 自定义验证可以提供帮助的一种方式?感谢回复
  • 啊,如果有管理员,那么没有其他类型可能有权限?
  • 现在关系是'admin'类型和'guest'类型。不知道以后这种关系有没有变化。如何进行自定义 ajv 验证以适应任何近期架构更改以适应这种复杂性

标签: json jsonschema json-schema-validator ajv


【解决方案1】:

使用 JSON Schema 执行此操作似乎有点棘手,但这是可能的。

您需要能够有条件地检查否定条件。

因此,您需要将ifthennot 结合使用。

首先条件:如果有管理员用户。使用if,我们可以有条件地应用进一步的检查规则。

接下来,检查:来宾用户不能拥有rights

thenif 通过验证时应用。然后,我们需要使用not 来否定guest 具有rights 的检查。

您可以通过使用 https://jsonschema.dev 提供的示例预期无效 JSON 数据看到正确失败的验证(链接已预加载此架构和您提供的实例数据。顺便说一句,它在浏览器中使用 AJV。)


更新:我已更新架构以满足您的其他要求。 我还更新了上面的演示链接。

架构现在只允许管理员在 admin 存在的情况下拥有权限,如果 admin 存在,其他用户类型可能没有权限。数组中的一项也必须具有权限(根据您的要求)。

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "if": {
    "contains": {
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "const": "admin"
        }
      }
    }
  },
  "then": {
    "not": {
      "contains": {
        "required": [
          "type",
          "rights"
        ],
        "properties": {
          "type": {
            "not": {
              "const": "admin"
            }
          }
        }
      }
    }
  },
  "contains": {
    "type": "object",
    "required": ["rights"]
  },
  "items": {
    "type": "object",
    "properties": {
      "type": {
        "enum": [
          "guest",
          "admin"
        ]
      },
      "rights": {
        "type": "string"
      },
      "hyperLink": {
        "type": "string",
        "format": "uri"
      }
    }
  }
}

【讨论】:

  • 如何使它适用于更新后的模式,其中我们有 2 个附加属性,并且“项目”作为数组键,具有多个枚举类型作为对象。除此之外,“权利”是强制属性。请查看问题中的更新架构。
  • 我已经更新了答案。现在如果 admin 存在,其他用户可能没有权限,并且数组中至少有一项必须有权限。
  • 感谢您澄清这个问题。但是,现在我有一个最终更新的架构,我尝试使用您的方法,但最终它无法正常工作可能是因为架构发生了变化。我知道我问了很多,但是有人可以帮忙吗?我已在问题的 [09/29]************* 下更新了详细信息。谢谢
  • 不断改变你的问题被认为是不好的形式。它变成了一个不同的问题,因为第一部分得到了回答。如果您还有其他更复杂的问题,最好再问一个问题。您添加的内容与您原来的问题非常不同。
  • 问题更新为原始形式以保持解决方案的相关性。
猜你喜欢
  • 2015-06-10
  • 2020-09-08
  • 2022-03-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-05
  • 2012-03-15
  • 2011-07-20
  • 1970-01-01
相关资源
最近更新 更多