如何定义具有可变必需属性的JSON模式

js5cn81o  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(128)

我想知道我是否可以定义一个JSON模式(草案2019-09),该模式至少需要对象的许多可能属性中的一个,有时需要多个这些属性。我已经知道allOf、anyOf、oneOf和dependantrequried,但就是不知道如何以我想要的方式使用它们。
我有一个有四个键的对象:

  • amount
  • productId
  • invoiceId
  • jwt

我有以下要求:

  • amountproductIdinvoiceId不能同时位于对象中
  • invoiceId必须有jwt
  • jwt可以单独使用,也可以与amountproduct一起使用
  • 必须至少有一个四个关键的对象将尊重上述规则。

我已经尝试过这个模式,在大多数情况下,除了jwt是单独的:

{
  "type": "object",
  "properties": {
    "amount": {"type": "number"},
    "productId": {"type": "string"},
    "invoiceId": {"type": "string"},
    "jwt": {"type": "string"},
  },
  "dependantRequried": {
    "invoiceId": ["jwt"]
  },
  "oneOf": [
    {"required": ["amount"]},
    {"required": ["productId"]},
    {"required": ["invoiceId"]},
  ]
}

{"required": ["jwt"]}添加到“oneOf”数组意味着当invoiceIdjwt在一起时它会失败。
预期结果:
| json| isValid|
| --------------|--------------|
| {"amount": 1}|真|
| {"amount": 1, "jwt": "jwt-test"}|真|
| {"productId": "prod-1"}|真|
| {"productId": "prod-1", "jwt": "jwt-test"}|真|
| {"invoiceId": "inv-1", "jwt": "jwt-test"}|真|
| {"jwt": "jwt-test"}|真|
| {"invoiceId": "inv-1"}|假的|
| {"amount": 1, "productId": "prod-1"}|假的|
| {"amount": 1, "productId": "prod-1", "jwt": "jwt-test"}|假的|

cclgggtu

cclgggtu1#

你有几个选择。

1. if / then / else

不要直接使用required,而是尝试使用if/then结构来禁止其他属性(如果存在)。

{
  // ...,
  "anyOf": [
    {
      "if": {"required": ["amount"]},
      "then": {
        "properties": {
          "productId": false,
          "invoiceId": false,
        }
      },
      "else": false
    },
    // repeat for productId and invoiceId
    {
      "properties": {
          "amount": false,
          "productId": false,
          "invoiceId": false
      }
    }
  ]
}

第一个子模式表示,如果示例中存在amount,则其他两个不能有值,这是一种不允许使用它们的迂回方式。对其他两个属性重复此操作。
最后一个涵盖了它们都不存在的情况。

2.使用properties即可

这基本上做了同样的事情,但有些人可能认为它可读性较差。这是一个风格问题,真的。

{
  // ...,
  "anyOf": [
    {
      "properties": {
          "amount": true,
          "productId": false,
          "invoiceId": false
      }
    },
    // repeat for productId and invoiceId
    {
      "properties": {
          "amount": false,
          "productId": false,
          "invoiceId": false
      }
    }
  ]
}

这里第一个子模式只允许amount属性。同样,对其他两个属性重复此操作,并具有相同的最后一种情况。
您还希望使用anyOf而不是oneOfoneOf可以工作,但它是一个更密集的检查。一些实现可以在找到一个有效的子模式后,对其他子模式进行简化而不进行评估。但是,对于oneOf,必须始终检查所有子模式。因为我们已经安排好了,所以只有一个是有效的,anyOf就可以了。
最后,你也有一个错字:dependantRequried -> dependentRequired
您可以在https://json-everything.net/json-schema上测试这些。

相关问题