如何使用可选的布尔值 属性 作为需要另一个 属性 的提示?

How do I use an optional boolean property as a hint to require another property?

想象一个 JSON 文档只有两个可能的属性:

  1. persist:布尔标志。默认为 true
  2. dbName: 一个字符串。

persisttrue 时,dbName 属性 必须 出现在文档中。当 persistfalse 时,dbName 属性 必须 而不是 文档。

看起来很简单——这是我想出的模式:

{
    "description": "Example",
    "$id": "https://example.com/example",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "persist": {
            "type": "boolean"
        },
        "dbName": {
            "type": "string"
        }
    },
    "additionalProperties": false,
    "oneOf": [
        {
            "$comment": "persist attr is present and == false, dbName should not be present",
            "properties": {
                "persist": {
                    "enum": [
                        false
                    ]
                }
            },
            "not": {
                "required": [
                    "dbName"
                ]
            }
        },
        {
            "$comment": "persist attr is present and == true, require dbName",
            "properties": {
                "persist": {
                    "enum": [
                        true
                    ]
                }
            },
            "required": [
                "dbName"
            ]
        },
        {
            "$comment": "persist attr is missing, its default value is true, require dbName",
            "properties": {
                "persist": false
            },
            "required": [
                "dbName"
            ]
        }
    ]
}

几乎 有效。三个测试文件来练习三种可能的情况:

{ "persist": true, "dbName": "dn" } --> 有效

{ "persist": false } --> 有效

{ "dbName": "dn" } --> 无效,错误如下:

[{
        keyword: 'not',
        dataPath: '',
        schemaPath: '#/oneOf/0/not',
        params: {},
        message: 'should NOT be valid'
    },
    {
        keyword: 'oneOf',
        dataPath: '',
        schemaPath: '#/oneOf',
        params: {
            passingSchemas: [Array]
        },
        message: 'should match exactly one schema in oneOf'
    }
]

通过反复试验,很明显最后一个文档实际上匹配 oneOf 中的两个条件:oneOf/1oneOf/2

我不知道为什么它会匹配 oneOf/1,因为 json 文档中没有 persist 属性。我确定我遗漏了一些明显的东西,非常感谢任何帮助。

在您对 oneOf 子模式的评论中,您曾说过您希望模式验证 persist 属性是否存在,但它没有。

我们来看看为什么会这样……

Validation succeeds if, for each name that appears in both the
instance and as a name within this keyword's value, the child
instance for that name successfully validates against the
corresponding schema.

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

这意味着,如果相应的键存在,值子模式将应用于对象中的实例值。如果没有,则不应用。

因此,如果您从 oneOf/1oneOf/2 中减去 properties,它们是等价的子模式。

你想要 oneOf/2 的是...

{
  "$comment": "persist attr is present and == true, require dbName",
  "properties": {
    "persist": {
      "const": true
    }
  },
  "required": [
    "persist",
    "dbName"
  ]
}

这是一个演示:https://jsonschema.dev/s/cqMDM

您也需要对 oneOf/0 进行相同的更改。

如果您没有按要求指定persist,子模式将不会检查键是否存在。