【问题标题】:JSON schema: conditional dependencyJSON模式:条件依赖
【发布时间】:2017-12-06 13:01:20
【问题描述】:

我似乎无法弄清楚如何在 JSON 模式中实现某些目标。假设我有两个字段:statusquote

条件依赖如下:

  • 如果status["Y", "N"],那么quote必需
  • 如果 status 是枚举中的任何其他内容,则 quote 不需要
  • 如果 status 不存在于 JSON 中,那么 quote 可以是任何东西

我正在尝试使用以下架构实现此行为:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "quote": {
      "type": "string",
    },

    "status": {
      "type": "string",
      "enum": ["Y", "N", "M", "A", "S"]
    }
  },
  
  "oneOf": [
      {
        "properties": {
          "status": {"enum": ["Y", "N"]}
        },
        "required": [
          "quote"
        ]
      },
      {
        "properties": {
          "status": {"enum": ["Y", "N", "M", "A", "S"]}
        }
      }
  ]
}

前两个条件按预期工作,但只要 JSON 中省略了 status 字段,验证就会失败。并且想要的行为是,只要status 字段不存在,我就可以拥有一个字段quote

我怎样才能做到这一点?

更新

所以我设法实现了我最初提出的要求,但是,我现在有了额外的要求。也就是说,只要status["M", "A"],我就有一个额外的字段author,否则它只是可选的。如果status 不存在,则quoteauthor 都可以是任何东西。我尝试如下:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "quote": { "type": "string" },
    "author": { "type": "string" },
    "status": { "enum": ["Y", "N", "M", "A", "S"] }
  },
  "allOf": [
    { "$ref": "#/definitions/y-or-n-requires-quote" },
    { "$ref": "#/definitions/m-or-a-requires-author" }
  ],
  "definitions": {
    "y-or-n-requires-quote": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/status-is-y-or-n" } },
        { "required": ["quote"] }
      ]
    },
    "m-or-a-requires-author": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/status-is-m-or-a" } },
        { "required": ["author"] }
      ]
    },
    
    "status-is-y-or-n": {
      "properties": {
        "status": { "enum": ["Y", "N"] }
      }
    },
    
    "status-is-m-or-a": {
      "properties": {
        "status": { "enum": ["M", "A"] }
      }
    }
  }
}

但是,对于不存在 status 的 JSON,使用此架构不起作用。

【问题讨论】:

    标签: json jsonschema


    【解决方案1】:

    请注意,draft-07 添加了“if”/“then”/“else”关键字以使条件更容易:

    https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-00#section-6.6

    如果您的工具不支持 Draft-07,请考虑提交功能请求以更新它们:-)

    【讨论】:

      【解决方案2】:

      您需要使用称为蕴含(!A 或 B)的布尔逻辑概念。这是一种表达 if-then 约束的方式。在这种情况下,我们要表达的是:要么状态不是“Y”/“N”,要么需要引用。

      {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "type": "object",
        "properties": {
          "quote": { "type": "string" },
          "status": { "enum": ["Y", "N", "M", "A", "S"] }
        },
        "allOf": [
          { "$ref": "#/definitions/y-or-n-requires-quote" }
        ],
        "definitions": {
          "y-or-n-requires-quote": {
            "anyOf": [
              { "not": { "$ref": "#/definitions/status-is-y-or-n" } },
              { "required": ["quote"] }
            ]
          },
          "status-is-y-or-n": {
            "properties": {
              "status": { "enum": ["Y", "N"] }
            },
            "required": ["status"]
          }
        }
      }
      

      【讨论】:

      • 嗯,谢谢,那行得通。但是,如果状态是 ["M" 或 "A"] 时我还需要,那么需要 "author" 属性怎么办?如果状态不是“M”或“A”,那么“作者”是可选的。因此,除了在此版本中有效的“引用”部分。你能更新你的答案吗?
      • 我不确定何时有机会更新答案,但这种技术适用于您需要的任何数量的含义。只需确定另一个含义并将其添加到allOf
      • 请看我的更新。我尝试了像你说的那样,但它不像我尝试的那样工作。它在“状态”存在时起作用,但只要“状态”不存在,验证就会失败。而且我希望能够只有“作者”字段或“引用”字段。 (当“作者”和“引用”都存在时有效)
      • @wesleyy “status-is-y-or-n”定义应该需要“status”属性。我已经更新了我的答案。这样,它应该可以按预期工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-06
      • 2017-11-09
      相关资源
      最近更新 更多