Python jsonschema 无法验证 JSON 模式条件嵌套属性

问题描述

重新发布问题How to implement conditional nested properties with JSON Schema标记为重复,但它是一个完全不同的问题) 我的 JSON 架构读取如下基于:JSON Schema if/then require nested object

{
  "$id": "myschema.json","if":{
    "type":"object","properties": {
      "common_data": {
        "type":"object","properties":{
          "remote_os": {
              "type":"object","required":["common_data"],"const": "Linux"
            }
          },"required":["remote_os"]
      }
    }
  },"then": {
    "type":"object","properties": {
      "file": {
        "type": "string","pattern": "^(.*.)(bin)$"
        }
      }
  },"else": {
    "type":"object","pattern": "^(.*.)(exe)$"
        }
      }
  }
}

基本上添加 if-else 逻辑以确保 remote_os=Linux file 应以 .bin 结尾,而 remote_os=Windows file 应以.exe 现在我正在尝试根据以下数据进行验证

{
  "common_data": {
    "remote_os": "Linux"
  },"file": "abc.bin"
}

出现错误[<ValidationError: "'abc.bin' does not match '^(.*.)(exe)$'">]

当尝试调试哪些属性时,python jsonschema 试图在此架构之上构建以验证我的数据。收到这个

properties {'common_data': {'type': 'object','properties': {'remote_os': {'type': 'object','required': ['common_data'],'const': 'Linux'}},'required': ['remote_os']}}
properties {'remote_os': {'type': 'object','const': 'Linux'}}
properties {'file': {'type': 'string','pattern': '^(.*.)(exe)$'}}

所以它总是与 'pattern': '^(.*.)(exe)$' 匹配,而不管 remote_os。寻求一些指导,了解如何解决此问题。

解决方法

您已经接近了,但存在一些问题。

首先,让我们评估我们的假设是否正确...看起来 if 失败了,并且触发了要应用的 else 架构值而不是 then 架构值。我们可以通过将 if 更改为简单的 true 来检查这一点。

是的,then 子模式在应用时可以正常工作。

好的,让我们移除嵌套模式的一部分,直到它按预期工作......

啊...看。 remote_os 在我们的数据中是一个字符串,但它已在模式中定义为一个对象。删除 type: object

那些 required 关键字与数据位置不匹配......它们只需要向上移动到正确的级别......

我们最终得到了这个架构: (现场演示:https://jsonschema.dev/s/CEwMw

{
  "$schema": "http://json-schema.org/draft-07/schema","$id": "myschema.json","if": {
    "type": "object","required": [
      "common_data"
    ],"properties": {
      "common_data": {
        "type": "object","required": [
          "remote_os"
        ],"properties": {
          "remote_os": {
            "const": "Linux"
          }
        }
      }
    }
  },"then": {
    "type": "object","properties": {
      "file": {
        "type": "string","pattern": "^(.*.)(bin)$"
      }
    }
  },"else": {
    "type": "object","pattern": "^(.*.)(exe)$"
      }
    }
  }
}

此外,另一个模式调试技巧是取出 if 模式值,并将其用作整个模式。这样您就可以找出验证失败的原因,而不仅仅是猜测。

这些是很容易犯的错误!我在尝试修复它时做了一些。重要的是要知道如何调试您的架构。测试假设,并识别子模式。