【问题标题】:Json schema add property on if conditionJson 模式在 if 条件下添加属性
【发布时间】:2021-09-23 16:35:21
【问题描述】:

在 JSON 模式中,我想添加一个验证,如果有效负载匹配如下

{
   "key1": "value1", 
   "key1": "value2"
}

然后期望第三个键“key3”具有任何值。

但如果 key1 和 key2 的值​​分别与 value1、value2 不匹配,则 key3 不应该存在。

JSON 架构如下所示

{
  "$async": true,
  "additionalProperties": false,
  "properties": {
    "key1": {
      "type": "string"
    }, 
    "key2": {
      "type": "string"
    }
  },
  "required": ["key1"],
  "allOf": [
    {
      "if": {
        "properties": {
          "key1": {
            "const": "value1"
          }, 
          "key2": {
            "const": "value2"
          }
        }
      },
      "then": {
        "properties": {
          "key3": {
            "type": "string"
          }
        },
        "required": ["key3"]
      },
      "else": {
      }
    }
  ]
}

有效的输入是

{
   "key1": "value1", 
   "key2": "value2", 
   "key3": "some-value"
}
--------
{
    "key1": "value1", 
    "key2": "other-value"
}
---------
{
    "key1": "value1"
}
---------
{
    "key1": "other-value", 
    "key2": "value2"
}
---------
{
    "key1": "other-value1", 
    "key2": "other-value2"
}

无效的输入是

{
   "key1": "value1", 
   "key2": "value2".   // key3 should be present
}
--------
{
   "key1": "hello", 
   "key2": "world",  
   "unexpected-key": "value"   // Any other key should not be allowed 
}
--------
{
    "key1": "value1", 
    "key2": "other-value", 
    "key3": "abc"    // should not be present
 
}
---------
{
    "key1": "other-value", 
    "key2": "value2",
    "key3": "abc"    // should not be present
}
---------
{
    "key1": "other-value1", 
    "key2": "other-value2",
    "key3": "abc"    // should not be present
}

对于下面的有效载荷,JSON schema validator

{
  "key1": "value1", 
  "key2": "value2", 
  "key3": "abc"
}

抛出以下错误

Property 'key3' has not been defined and the schema does not allow additional properties.

如何实现这个条件属性?

【问题讨论】:

  • 我想要的是条件属性。这和问题说的不一样吗?
  • 抱歉,我误读了这个问题。我将撤回我的投票以结束并为您提供答案! =]
  • 如果您包含适合您情况的真实值而不是 foo/bar 类型值,这将很有帮助。不太可能误读问题=]
  • 我个人认为添加真实值会使问题更难理解。因为读者必须先了解领域问题,然后再了解实际问题。而如果使用通用值,则可以减轻理解特定领域事物的负担。我认为给出的例子应该是不言自明的

标签: json jsonschema


【解决方案1】:

解决方案取决于您能够使用 JSON Schema 的版本(或“草案”)。 Draft 2019-09 或更高版本提供了更简洁的解决方案,但在 Draft-07 中仍然可以使用。

(在 if/then/else 引入之前也可以使用 implication method,但我今天不会讨论。

使用 2019-09 或 2020-12 的最佳解决方案。

unevaluatedProperties 关键字可以“透视”应用程序关键字,例如 allOfifelse

与 draft-07 的 additionalProperties 不同,unevaluatedProperties 在架构模式对象中的所有其他应用程序之后运行,并且可以了解在更深的嵌套应用程序中定义的成功验证的属性值。

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "unevaluatedProperties": false,
  "properties": {
    "key1": {
      "type": "string"
    },
    "key2": {
      "type": "string"
    }
  },
  "required": [
    "key1"
  ],
  "allOf": [
    {
      "if": {
        "required": ["key2"],
        "properties": {
          "key1": {
            "const": "value1"
          },
          "key2": {
            "const": "value2"
          }
        }
      },
      "then": {
        "required": ["key3"],
        "properties": {
          "key3": {
            "type": "string"
          }
        }
      }
    }
  ]
}

对于 2019-09 及更高版本的测试草稿,我建议使用 https://json-schema.hyperjump.io playground

https://jsonschema.dev 尚不支持草案 2019-09 及更高版本)。

使用draft-07的解决方案。

要使additionalProperties: false 工作,它需要在properties 的同一架构对象中定义属性(或匹配patternProperties)。

在第一种情况下,您不必关心具体的值,properties 对象中的值只是true。值验证稍后处理。如果你觉得它更干净,你可以把它移到顶层。

通过此更改,我们的 if/then 可以从您的示例中工作,除了它没有阻止 key3 应该有的时候。我们通过在else 中使用not 来解决这个问题。

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "additionalProperties": false,
  "properties": {
    "key1": {
      "type": "string"
    }, 
    "key2": {
      "type": "string"
    },
    "key3": true
  },
  "required": ["key1"],
  "allOf": [
    {
      "if": {
        "required": ["key2"],
        "properties": {
          "key1": {
            "const": "value1"
          }, 
          "key2": {
            "const": "value2"
          }
        }
      },
      "then": {
        "required": ["key3"],
        "properties": {
          "key3": {
            "type": "string"
          }
        }
      },
      "else": {
        "not": {
          "required": ["key3"]
        }
      }
    }
  ]
}

演示:https://jsonschema.dev/s/ZTi4X

【讨论】:

  • 感谢@Relequestual 的详细回答。我会检查这个并回复你。
猜你喜欢
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 2021-05-15
  • 1970-01-01
  • 2020-09-23
  • 2022-11-18
  • 1970-01-01
相关资源
最近更新 更多