JSON 不同 属性 值的架构验证

JSON Schema validation for different property values

我正在尝试验证以下 JSON 文件:

{
"Transaction": {
    "Header": {
        "Workflow": "Rejection",
        "Job-Offer": {
            "Offer-Status": "New",
            "Datetime-Offered": "2017-12-15T16:00:00",
            "Accepted": "YES",
            "Datetime-Accepted": "2017-12-15T16:00:00"
        }
    }
}

}

针对以下架构:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Schema",
"description": "Schema",
"$ref": "#/defs/Schema",
"defs": {
    "Schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "Transaction": {
                "$ref": "#/defs/Transaction"
            }
        },
        "required": [
            "Transaction"
        ],
        "title": "Schema"
    },
    "Transaction": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "Transaction-Header": {
                "$ref": "#/defs/Transaction-Header"
            }
        },
        "required": [
            "Transaction-Header"
        ],
        "title": "Transaction"
    },
    "Transaction-Header": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "Workflow": {
                "type": "string",
                "enum": [
                    "Offer",
                    "Transfer",
                    "Acceptance",
                    "Rejection",
                    "Cancellation",
                    "Update"
                ]
            },
            "Job-Offer": {
                "$ref": "#/defs/JobOffer"
            }
        },
        "required": [
            "Workflow"
        ],
        "title": "Transaction-Header"
    },
    "JobOffer": {
        "description": "Job Offer.",
        "type": "object",
        "additionalProperties": true,
        "properties": {
            "Offer-Status": {
                "type": "string",
                "enum": [
                    "New",
                    ""
                ]
            },
            "Datetime-Offered": {
                "type": "string",
                "format": "date-time"
            },
            "Accepted": {
                "type": "string",
                "enum": [
                    "YES",
                    "NO",
                    ""
                ]
            },
            "Datetime-Accepted": {
                "type": "string",
                "format": "date-time"
            },
            "Reason-Rejected": {
                "type": "string",
                "minLength": 0,
                "maxLength": 30
            },
            "Offer-Cancelled": {
                "type": "string",
                "enum": [
                    "YES",
                    "NO",
                    ""
                ]
            },
            "Datetime-Cancelled": {
                "type": "string",
                "format": "date-time"
            }
        },
        "allOf": [
            { "$ref": "#/defs/JOBACCEPT" },
            { "$ref": "#/defs/JOBREJECT" }
        ],
        "required": [
            "Offer-Status"
        ],
        "title": "JobOffer"
    },
    "JOBACCEPT": {
        "properties": {
            "Workflow": { "enum": [ "Acceptance" ] }
        },
        "required": [ 
            "Accepted",
            "Datetime-Accepted" 
        ],
    },
    "JOBREJECT": {
        "properties": {
            "Workflow": { "enum": [ "Rejection" ] }
        },
        "required": [ 
            "Reason-Rejected" 
        ],
    }
}

}

我追求的是:

如果选择“接受”的工作流程,则需要填写JOBACCEPT下的字段。 如果选择“拒绝”的工作流程,则JOBREJECT下的字段是必填项。

我已经尝试了 oneOf、allOf、anyOf、if-then-else 的许多不同组合,但似乎没有任何一个能正常工作。

有人知道需要做什么吗?

重新处理 json 内联:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"type": "object",
"properties": {
  "Transaction": {
    "type": "object",
    "properties": {
      "Transaction-Header": {
        "type": "object",
        "properties": {
          "Workflow": {
            "type": "string",
            "enum": [
              "Offer",
              "Transfer",
              "Acceptance",
              "Rejection",
              "Cancellation",
              "Update"
            ]
          },
          "Job-Offer": {
            "type": "object",
            "properties": {
              "Offer-Status": {
                "type": "string",
                "enum": [
                  "New",
                  ""
                ]
              },
              "Datetime-Offered": {
                "type": "string",
                "format": "date-time"
              },
              "Accepted": {
                "type": "string",
                "enum": [
                  "YES",
                  "NO",
                  ""
                ]
              },
              "Datetime-Accepted": {
                "type": "string",
                "format": "date-time"
              },
              "Reason-Rejected": {
                "type": "string",
                "minLength": 0,
                "maxLength": 30
              },
              "Offer-Cancelled": {
                "type": "string",
                "enum": [
                  "YES",
                  "NO",
                  ""
                ]
              },
              "Datetime-Cancelled": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "Offer-Status"
            ]
          },
          "readOnly": true
        },
        "required": [
          "Workflow"
        ]
      }
    },
    "required": [
      "Transaction-Header"
    ]
  }
},
"allOf": [
  {
    "if": {
      "properties": {
        "Transaction": {
          "properties": {
            "Transaction-Header": {
              "properties": {
                "Workflow": {
                  "enum": [
                    "Acceptance"
                  ]
                }
              },
              "required": [
                "Workflow"
              ]
            }
          }
        }
      }
    },
    "then": {
      "properties": {
        "Transaction": {
          "properties": {
            "Transaction-Header": {
              "properties": {
                "Job-Offer": {
                  "properties": {},
                  "required": [
                      "Accepted",
                      "Datetime-Accepted"
                    ]
                }
              }
            }
          }
        }
      }
    }
  }
],
"required": [
  "Transaction"
]}

您将所有内容都抽象为定义*,因此很难表达引用多层深层事物的条件。如果您内联所有定义,就会更容易看到需要做什么。

if/then 关键字需要处于 'Transaction' 级别。在伪代码中:

”如果 属性 'Header' 存在(即 required)并且它的值为 ...(const),则需要 属性 。 .. 具有值(类型=对象,所需属性=[...],属性 定义=...)”,等等。

* 顺便说一下,在 2020-12 版中,定义关键字是 $defs——它可能会按照您的方式工作,但实现将无法验证模式 undef defs因为他们不会在那里认出它们,所以一些错误可能会漏掉并且更难找到。

你的想法是对的。问题是您将 allOf 与条件句放在一起的位置。您在“JobOffer”架构中拥有它,但正在尝试对“Transaction-Header”架构中的“Workflow”属性 设置约束。无法引用 JSON 树结构中更高层的 属性,因此您需要将 allOf 向上移动到“Transaction-Header”架构中,以便您可以对“工作流程”设置约束 属性.

现在它位于正确的位置,表达条件约束的最佳方式是使用 if/thenif/then 的上下文现在是“Transaction-Header”模式,因此 then 模式不仅需要说明需要什么属性,还需要声明这些属性在“Job-Offer”对象中。

{
  ...

  "defs": {
    ...

    "Transaction-Header": {
      ...

      "allOf": [
        { "$ref": "#/defs/JOBACCEPT" },
        { "$ref": "#/defs/JOBREJECT" }
      ]
    },

    "JOBACCEPT": {
      "if": {
        "type": "object",
        "properties": {
          "Workflow": { "enum": ["Acceptance"] }
        },
        "required": ["Workflow"]
      },
      "then": {
        "properties": {
          "Job-Offer": {
            "required": ["Accepted", "Datetime-Accepted"]
          }
        }
      }
    },

    "JOBREJECT": { ... Similar to JOBACCEPT ... }
  }
}