JSON 架构中的多个条件,draft-04

问题描述 投票:0回答:1

我有这个字段

assignments
:

  • chapters
    在赋值对象中是可选的。
  • type
    为必填项。
  • 当类型为
    multi
    时:
    pointer
    值应该存在于每个
    chapters
    对象中,如果其
    不是父
    assignments
    对象的一部分。
  • 当类型为
    notes
    时:
    pointer
    是必需的,除非
    completed
    为真。
{
    "assignments": [
        {
            "type": "multi",
            "pointer": "1",
            "chapters": [
                {
                    "id": "203"
                },
                {
                    "id": "204"
                }
            ]
        },
        {
            "type": "multi",
            "chapters": [
                {
                    "id": "201",
                    "pointer": "3"
                },
                {
                    "id": "202",
                    "pointer": "3"
                }
            ]
        },
        {
            "type": "notes",
            "pointer": "4"
        },
        {
            "type": "notes",
            "completed": true
        }
    ]
}

为了使用 json-schema.org/draft-04 验证此架构,我不确定如何满足嵌套依赖项的所有条件。我已经尝试了以下模式,但它没有按预期工作。 由于验证

pointer
的预期完成为 false,因此
completed
是可选的,并且仅在必须设置为
true
时才会出现。对于类型
multi
,当
pointer
pointer
的一部分时,期望
chapters
出现。

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "assignments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["multi", "notes"]
          },
          "pointer": {
            "type": "string"
          },
          "completed": {
            "type": "boolean"
          },
          "chapters": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "pointer": {
                  "type": "string"
                }
              },
              "required": ["id"]
            }
          }
        },
        "required": ["type"],
        "dependencies": {
          "type": {
            "oneOf": [
              {
                "properties": {
                  "type": { "enum": ["multi"] }
                },
                "oneOf": [
                  {
                    "properties": {
                      "pointer": { "type": "string" }
                    }
                  },
                  {
                    "properties": {
                      "chapters": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "pointer": { "type": "string" }
                          },
                          "required": ["pointer"]
                        }
                      }
                    }
                  }
                ]
              },
              {
                "properties": {
                  "type": { "enum": ["notes"] },
                  "completed": { "enum": [true] }
                }
              },
              {
                "properties": {
                  "type": { "enum": ["notes"] }
                },
                "required": ["pointer"]
              }
            ]
          }
        }
      }
    }
  },
  "required": ["assignments"]
}

示例:

  1. 示例1
{
  "assignments": [
    {
      "type": "notes",
      "completed": true
    }
  ]
}
  • 预期结果:应该通过
  • 实际结果:通过
  1. 示例2
{
  "assignments": [
    {
      "type": "notes",
      "pointer": "4"
    }
  ]
}
  • 预期结果:应该通过
  • 实际结果:
    notes is not a valid enum value,#/assignments/0: #: 2 subschemas matched instead of one
  1. 示例3
{
  "assignments": [
    {
      "type": "notes"
    }
  ]
}
  • 预期结果:失败,找不到所需的密钥[指针]
  • 实际结果:通过
  1. 示例4
{
  "assignments": [
    {
      "type": "multi",
      "chapters": [
        {
          "id": "201",
          "pointer": "3"
        },
        {
          "id": "202",
          "pointer": "3"
        }
      ]
    }
  ]
}
  • 预期结果:失败,找不到所需的密钥[指针]
  • 实际结果:通过
  1. 示例5
{
  "assignments": [
    {
      "type": "multi",
      "pointer": "4",
      "chapters": [
        {
          "id": "201"
        },
        {
          "id": "202"
        }
      ]
    }
  ]
}
  • 预期结果:应该通过
  • 实际结果:失败并显示
    multi is not a valid enum value,#/assignments/0: #: 2 subschemas matched instead of one, multi is not a valid enum value,#/assignments/0: required key [pointer] not found
  1. 示例6
{
  "assignments": [
    {
      "type": "multi",
      "chapters": [
        {
          "id": "201",
          "pointer": "4"
        },
        {
          "id": "202",
          "pointer": "4"
        }
      ]
    }
  ]
}
  • 预期结果:应该通过
  • 实际结果:通过
  1. 示例7
{
  "assignments": [
    {
      "type": "multi",
      "chapters": [
        {
          "id": "201",
          "pointer": "4"
        },
        {
          "id": "202"
        }
      ]
    }
  ]
}
  • 预期结果:失败,找不到所需的键[指针](
    pointer
    应该出现在“章节”数组之外,或者应该是每个“章节”对象的一部分)
  • 实际结果:通过
jsonschema
1个回答
0
投票

不幸的是,draft-04 需要一个大而冗长的模式来实现条件行为。

这在 Draft-07 或更新版本中更加清晰。

我已将每个条件模块化在

definitions
条目中,然后使用
oneOf
来引用每个条件。错误输出非常详细,因为它需要报告评估过程中的每一个失败。

这里需要考虑的几件事是以下用例:

  • 示例 3:模式中缺失的
    type: notes
    completed
    未涵盖。无法评估缺少的关键字。
  • 示例 4:您的预期结果似乎不正确。您说
    pointer
    对父母或孩子有效,而不是两者都有效。所以这件事正如我所想的那样通过了。
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "required": [
    "assignments"
  ],
  "properties": {
    "assignments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "type": {},
          "pointer": {
            "type": "string"
          },
          "completed": {
            "type": "boolean"
          },
          "chapters": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "pointer": {
                  "type": "string"
                }
              }
            }
          }
        },
        "oneOf": [
          {
            "$ref": "#/definitions/multi-pointer-in-child"
          },
          {
            "$ref": "#/definitions/multi-pointer-at-root"
          },
          {
            "$ref": "#/definitions/notes-completed:false"
          },
          {
            "$ref": "#/definitions/notes-completed:true"
          }
        ]
      }
    }
  },
  "definitions": {
    "multi-pointer-in-child": {
      "properties": {
        "type": {
          "enum": [
            "multi"
          ]
        },
        "chapters": {
          "minItems": 1,
          "items": {
            "required": [
              "pointer"
            ]
          }
        },
        "completed": {}
      },
      "required": [
        "type"
      ],
      "not": {
        "required": [
          "pointer"
        ]
      },
      "additionalProperties": false
    },
    "multi-pointer-at-root": {
      "properties": {
        "type": {
          "enum": [
            "multi"
          ]
        },
        "pointer": {},
        "chapters": {
          "items": {
            "not": {
              "required": [
                "pointer"
              ]
            }
          }
        },
        "completed": {}
      },
      "required": [
        "type"
      ],
      "additionalProperties": false
    },
    "notes-completed:false": {
      "additionalProperties": false,
      "properties": {
        "type": {
          "enum": [
            "notes"
          ]
        },
        "chapters": {},
        "completed": {
          "enum": [
            false
          ]
        },
        "pointer": {}
      },
      "required": [
        "type",
        "pointer"
      ]
    },
    "notes-completed:true": {
      "additionalProperties": false,
      "properties": {
        "type": {
          "enum": [
            "notes"
          ]
        },
        "chapters": {},
        "completed": {
          "enum": [
            true
          ]
        }
      },
      "required": [
        "type"
      ],
      "not": {
        "required": [
          "pointer"
        ]
      }
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.