【问题标题】:Use json-schema to require or disallow properties based on another property value?使用 json-schema 来要求或禁止基于另一个属性值的属性?
【发布时间】:2018-10-24 17:49:00
【问题描述】:

我要在 json-schema 中完成的工作:当属性 enabledtrue 时,应该需要某些其他属性。当false 时,应该禁止这些属性。

这是我的 json 模式:

{
  "type": "object",
  "properties": {
    "enabled": { "type": "boolean" }
  },
  "required" : ["enabled"],
  "additionalProperties" : false,
  "if": {
    "properties": {
      "enabled": true
    }
  },
  "then": { 
    "properties": {
      "description" : { "type" : "string" },
      "count": { "type": "number" }
    },
    "required" : ["description", "count"]
  }
}

使用ajv 6.5 版进行验证,无论enabled 的值如何,都需要count 等。例如,对于数据:

{ "enabled": false }

我的验证错误是:

[ { keyword: 'required',
    dataPath: '',
    schemaPath: '#/then/required',
    params: { missingProperty: 'description' },
    message: 'should have required property \'description\'' },
  { keyword: 'required',
    dataPath: '',
    schemaPath: '#/then/required',
    params: { missingProperty: 'count' },
    message: 'should have required property \'count\'' },
  { keyword: 'if',
    dataPath: '',
    schemaPath: '#/if',
    params: { failingKeyword: 'then' },
    message: 'should match "then" schema' } ]

如何使用 json-schema draft-7 完成此操作?

请注意,此问题与
jsonSchema attribute conditionally required 类似,但要求更严格。

【问题讨论】:

  • @Jason 不是重复的。大同小异,只是这个问题要求更严格。
  • 我不同意。这是标记为“Enum”的策略的一个非常简单的用例。实际上,您在下面的答案使用了该策略。您的答案应标记为已接受的答案。这比if-then-else 的答案好多了。
  • 我同意接受我自己的答案(在 5 小时内),因为这可能是解决我问题的更优雅的方法。我认为这个问题不是重复的,因为它提出了一个不同的(如果相关的话)问题。我不止一次阅读了您对另一个问题的(优秀)答案,但仍然不知道如何解决我/这个特定问题。虽然这里的“枚举”策略变体的适用性对于熟练的从业者 来说可能是显而易见的,但作为新手,我可以说这对我来说并不明显。最好为这个案子写清楚,以可能拯救其他挣扎的人。

标签: jsonschema ajv


【解决方案1】:

为此,您需要在if 语句中使用const 关键字,因此架构将如下所示:

{
  "type": "object",
  "properties": {
    "enabled": { "type": "boolean" }
  },
  "required" : ["enabled"],
  "additionalProperties" : false,
  "if": {
    "properties": {
      "enabled": {"const": true}
    }
  },
  "then": { 
    "properties": {
      "description" : { "type" : "string" },
      "count": { "type": "number" }
    },
    "required" : ["description", "count"]
  }
}

【讨论】:

    【解决方案2】:

    这受到 vearutop 出色回答的启发。我认为它可能会更短一些,并且可以实现我的既定目的。

    {
      "type": "object",
      "oneOf" : [
        {
          "properties": {
            "enabled": { "const": false }
          },
          "required": ["enabled"],
          "additionalProperties": false
        },
        {
          "properties": {
            "enabled": { "const": true },
            "description": { "type": "string" },
            "count": { "type": "number" }
          },
          "required": [ "enabled", "description", "count"],
          "additionalProperties": false
        }
      ]
    }
    

    正如 cmets 中所指出的,这是 this answer 中阐明的 Enum 策略的特定变体。

    【讨论】:

      【解决方案3】:

      试试这个架构:

      {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled"
        ],
        "if": {
          "properties": {
            "enabled": {
              "const": true
            }
          }
        },
        "then": {
          "properties": {
            "enabled": {
              "type": "boolean"
            },
            "description": {
              "type": "string"
            },
            "count": {
              "type": "number"
            },
            "additionalProperties": false
          },
          "required": [
            "description",
            "count"
          ]
        },
        "else": {
          "properties": {
            "enabled": {
              "type": "boolean"
            }
          },
          "additionalProperties": false
        }
      }
      

      如果您需要"additionalProperties": false,您必须枚举thenelse 中的所有属性。如果您可以接受其他属性,则架构可能会更简单:

      {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled"
        ],
        "if": {
          "properties": {
            "enabled": {
              "const": true
            }
          }
        },
        "then": {
          "properties": {
            "description": {
              "type": "string"
            },
            "count": {
              "type": "number"
            }
          },
          "required": [
            "description",
            "count"
          ]
        }
      }
      

      我检查过ajv cli

      有效:{"enabled": false}

      无效:{"enabled": true}

      有效:{"enabled": true, "description":"hi", "count":1}

      【讨论】:

        猜你喜欢
        • 2021-11-11
        • 2018-04-18
        • 2014-04-19
        • 1970-01-01
        • 2020-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多