首页 > 解决方案 > 如何验证可以包含作为不同类型对象的项目的数组

问题描述

我有一个模式,其中我有一个数组(在传输对象内),它可能有两个选项(A 或 B)之一。

我已经附加了模式和示例数据(当它应该抛出错误时,它实际上正在得到验证)。

在transmitDataDef->items下,我尝试了“anyOf”、“oneOf”、“type”,即使数据不匹配,它们都不会出错(数据包含未在任何地方定义的optionC)

我正在使用 jsonschema python 库。我也在https://www.jsonschemavalidator.net/中尝试过这个模式 + 数据,结果相同。

架构:

{
  "definitions": {
    "optionADef": {
      "type": "object",
      "properties": {
        "pattern": {
          "type": "string",
          "enum": [
            "random",
            "fixed"
          ]
        },
        "startbyte": {
          "type": "number"
        }
      },
      "required": [
        "startbyte"
      ],
      "additionalProperties": false
    },
    "optionBSubItemDef": {
      "type": "object",
      "properties": {
        "value": {
          "type": "number",
          "minimum": 0
        }
      }
    },
    "optionBSettingsDef": {
      "type": "object",
      "properties": {
        "sequence": {
          "type": "number",
          "minimum": 0
        }
      }
    },
    "optionBDataDef": {
      "type": "object",
      "properties": {
        "subitem": {
          "ref": "#/definitions/optionBSubItemDef"
        }
      }
    },
    "optionBDef": {
      "type": "object",
      "properties": {
        "_data": {
          "ref": "#/definitions/optionBDataDef"
        },
        "_settings": {
          "$ref": "#/definitions/optionBSettingsDef"
        }
      },
      "required": [
        "_data"
      ],
      "additionalProperties": false
    },
    "transmitDataDef": {
      "type": "array",
      "minItems": 1,
      "maxItems": 1,
      "items": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "optionA": {
                "ref": "#/definitions/optionADef"
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "optionB": {
                "ref": "#/definitions/optionBDef"
              }
            },
            "additionalProperties": false
          }
        ]
      }
    },
    "transmitSettingsDef": {
      "type": "object",
      "properties": {
        "length": {
          "type": "number",
          "minimum": 0,
          "maximim": 8
        }
      }
    },
    "transmitDef": {
      "type": "object",
      "properties": {
        "_data": {
          "ref": "#/definitions/transmitDataDef"
        },
        "_settings": {
          "$ref": "#/definitions/transmitSettingsDef"
        }
      },
      "required": [
        "_data"
      ],
      "additionalProperties": false
    },
    "bundleDef": {
      "type": "object",
      "properties": {
        "transmit": {
          "$ref": "#/definitions/transmitDef"
        }
      },
      "oneOf": [
        {
          "required": [
            "transmit"
          ]
        }
      ],
      "additionalProperties": false
    }
  },
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "bundle": {
      "$ref": "#/definitions/bundleDef"
    }
  },
  "required": [
    "name",
    "bundle"
  ]
}

样本数据:

{
  "name": "test1",
  "bundle": {
    "transmit": {
      "_settings": {
        "length": 0
      },
      "_data": [
        {
          "optionC": {
            "_settings": {
              "sequence": 150
            },
            "data1": [
              {
                "subitem": {
                  "value": 100
                }
              }
            ]
          }
        }
      ]
    }
  }
}

我希望验证能够捕获“optionC”并将其标记为错误。如果我有 optionB 而不是 optionC,我希望它将“data1”标记为无效项目。

标签: jsonschemapython-jsonschema

解决方案


你有正确的方法。我使用以下架构和实例验证了这一点,使用https://jsonschema.dev

架构:

{
  "properties": {
    "_data": {
      "type": "array",
      "items" : {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "inline": true
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "rewrite": true
            },
            "additionalProperties": false
          }
        ]
      }
    }
  }
}

实例 :

{
  "_data": [
    {
      "optionC": {
        "_settings": {
          "sequence": 150
        },
        "data1": [
          {
            "subitem": {
              "value": 100
            }
          }
        ]
      }
    }
  ]
}

除了您使用“anyOf”之外,还有其他问题,这是正确的。

它实际上是更简单的东西......

您在架构中的很多地方都使用了“ref”而不是“$ref”。未知关键字将被忽略,因此您的引用无效。

如果有什么安慰的话,我花了很长时间调试!


推荐阅读