Как проверить массив, который может содержать элементы, которые являются объектами разных типов - PullRequest
1 голос
/ 28 мая 2019

У меня есть схема, где у меня есть массив (внутри передающего объекта), который может иметь одну из двух опций (A или B).

Я приложил и схему, и данные образца (то естьна самом деле проверяется, когда он должен был выдать ошибку).

в элементах TransferDataDef->, я пробовал "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» как недопустимый элемент.

1 Ответ

1 голос
/ 28 мая 2019

У вас правильный подход.Я проверил это, используя следующую схему и экземпляр, используя 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" в вашей схеме довольномало местНеизвестные ключевые слова игнорируются, и поэтому ваши ссылки не работают.

Если это утешит, мне потребовалось много времени для отладки!

...