【问题标题】:Validating value combinations with jsonschema使用 jsonschema 验证值组合
【发布时间】:2020-01-28 21:35:09
【问题描述】:

我正在使用 jsonschema 来验证配置文件。 目前我在验证嵌套属性的值组合时遇到了麻烦。

我最初实现了 if/then/else,但经过几次传递后没有看到所需的行为。 对 switch、依赖项和最后使用的含义也是如此。

这是我的架构:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "account_group": {
      "type": "string"
    },
    "region": {
      "type": "string",
      "pattern": "^(us(-gov)?|ap|ca|cn|eu|sa)-(central|(north|south)?(east|west)?)-\\d$"
    },
    "appid": {
      "type": "string"
    },
    "services": {
      "type": "object",
      "minProperties": 1,
      "patternProperties": {
        "^[A-Za-z_]*$": {
          "type": "object",
          "properties": {
            "source": {
              "type": "string"
            },
            "port": {
              "type": "number"
            },
            "cpu": {
              "type": "number",
              "enum": [256, 512, 1024, 2048, 4096]
            },
            "memory": {
              "type": "number",
              "enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
                12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                22, 23, 24, 25, 26, 27, 28, 29, 30]
            }
          },
          "required": [
            "source",
            "port",
            "cpu",
            "memory"
          ],
        }
      },
      "additionalProperties": false
    },
    "stages": {
      "type": "object",
      "minProperties": 1
    },
    "workingDirectory": {
      "type": "string"
    }
  },
  "required": [
    "name",
    "account_group",
    "appid",
    "services"
  ]
}

注意:我删除了我最新的 allOf 块以避免显示我已经测试过的损坏代码

我想要完成的是验证配置文件中 cpu/内存值的正确组合,并与架构进行比较。

组合是:

256/[0.5, 1, 2]
512/[1-4]
1024/[2-8]
2048/[2-16]
4096/[2-30]

有人会建议适当的架构设计来验证这些组合吗?

本质上,如果 cpu 为 256,并且内存值不是 0.5、1、2,则我需要验证失败 - 如果 cpu 为 512 并且内存值不是 1 - 4 等,则验证失败。

我已经得到了最接近的使用含义,但是我看到了许多使用依赖项的组合,这进一步使我感到困惑。我个人觉得 if/then/else 是最合乎逻辑的方法,但它并没有产生预期的行为。

【问题讨论】:

  • 今晚我会尽力回答这个问题,但如果我不能回答,这里是一般策略。使用allOf,其中每个模式都包含您尝试验证的条件之一。 if/then 可以正常工作。隐含模式与if/then 完全相同,只是更难。使用暗示模式的唯一原因是如果你没有if/thendependencies 在这种情况下不起作用。

标签: json jsonschema json-schema-validator


【解决方案1】:

if/then 是最好的选择。隐含模式也有效,但if/then 更好用。一般策略是为每个条件创建一个定义,然后使用allOf 将它们组合起来。您当然可以将条件内联而不是使用definitions,但这样读起来会更好,这使得维护更容易。我做了前两个来说明。您可以从那里推断。

{
  "type": "object",
  "properties": {
    "source": { "type": "string" },
    "port": { "type": "number" },
    "cpu": { "enum": [256, 512, 1024, 2048, 4096] },
    "memory": { "enum": [0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
                         12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                         22, 23, 24, 25, 26, 27, 28, 29, 30] }
  },
  "required": ["source", "port", "cpu", "memory"],
  "allOf": [
    { "$ref": "#/definitions/if-cpu-256-then-memory-0.5-1-2" },
    { "$ref": "#/definitions/if-cpu-512-then-memory-1-4" }
  ],
  "definitions": {
    "if-cpu-256-then-memory-0.5-1-2": {
      "if": {
        "properties": {
          "cpu": { "const": 256 }
        },
        "required": ["cpu"]
      },
      "then": {
        "properties": {
          "memory": { "enum": [0.5, 1, 2] }
        }
      }
    },
    "if-cpu-512-then-memory-1-4": {
      "if": {
        "properties": {
          "cpu": { "const": 512 }
        },
        "required": ["cpu"]
      },
      "then": {
        "properties": {
          "memory": { "minimum": 1, "maximum": 4 }
        }
      }
    }
  }
}

【讨论】:

  • 这是一个非常干净的解决方案!
  • 感谢您的意见!我推断出我的其他案例并将其插入。由于 $ref 结构,我收到了 SchemaError ......正在调查它。还尝试内联编写 if/then 条件,但是应该失败的用例正在传递——这是我在最初传递时看到的行为。一旦我得到这个排序会跟进。
  • 您可能遇到问题,因为此答案中的架构将嵌套在更大的架构中。这将改变$refs 指向的路径。尝试将 definitions 移动到顶级架构。或者,将$id 放在此架构的顶部,这会将$ref 分辨率更改为相对于$id,并且它的嵌套位置无关紧要。
  • 我已将您的答案标记为已接受,因为架构的 if/else 块是正确的解决方案。我会注意到我在 js 中使用 'jsonschema' 的实现仍然没有按预期工作。我已经使用 jsonschemavalidator.net 针对我的测试配置文件验证了架构 - 将 definitions 块移动到顶级架构修复了架构错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多