首页 > 解决方案 > 如何在 JSON 模式中表示多态对象?

问题描述

我正在尝试为 JSON 对象创建一个模式,该对象根据其属性之一的值改变其模式:type.

像这样:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "type": {
      "type": "string",
      "enum": ["INT", "PERCENT"]
    }
  },
  "required": ["type"],
  "allOf": [
    {
      "if": {
        "properties": {"type": {"const": "INT"}}
      },
      "then": {
        "properties": {
          "value": {"type": "number", "multipleOf": 1}
        },
        "required": ["value"],
        "additionalProperties": false
      }
    },
    {
      "if": {
        "properties": {"type": {"const": "PERCENT"}}
      },
      "then": {
        "properties": {
          "value": {"type": "number"},
          "min": {"type": "number"},
          "max": {"type": "number"}
        },
        "required": ["value", "min", "max"],
        "additionalProperties": false
      }
    }
  ]
}

但是我从我正在尝试的各种验证器那里得到了各种各样的不当行为。

一些有问题的例子在后面提到//

{
    "type": "PERCENT", // property type has not been defined(?!)
    "value": 0.0,
    "min": 10,
    "max": 25
}

{
    "type": "INT", // no errors allowed, and value 
    "value": 0.1,  // should've been flagged as not multiple of 1
    "min": 10,  // should've been flagged as disallowed additional property
    "max": 25 // same as above
}

这是我正在尝试的验证器

在此先感谢您的帮助!

标签: jsonjsonschema

解决方案


看来您已经发现问题在于addtionalProperties只考虑在它定义的子架构中定义的属性。这就是为什么您必须在then. 您有几个选项可以改进您发布但您不满意的解决方案。

选项1:unevaluatedProperties

2019-09 草案引入了unevaluatedProperties关键字。如果您在架构的顶层使用它并且不在addtionalProperties任何地方使用,您将从additionalProperties. 我看到您使用的是 draft-07,因此您必须升级才能使用此解决方案。

选项 2:布尔模式

您提出的解决方案是在模式中重新定义“类型”属性thenadditionalProperties只需要声明“类型”,您不需要再次包含它的架构。您可以改用true或 空模式{}

选项 3:propertyNames

而不是additionalProperties你可以使用propertyNames. 这允许您声明对象中允许哪些属性名称的列表,而不是按照您想要的方式破解additionalPropertiestrue找出{}允许的属性名称。


推荐阅读