如何根据另一个属性的值设置架构对象的类型?

时间:2018-12-21 08:45:36

标签: jsonschema

我有一个对象(来自第三方),所以有一个名为“ key”的属性,另一个名为“ value”的属性是可选的,它的类型取决于对象的值“键”属性。

例如:
如果键为“注释”,则为值{"Text":"commentValue"}的类型。
如果键为“偏移”,则值的类型为{"seconds":int}
如果键为“天气”,则值的类型为{"value": Enum["sun", "clouds", "rain"...]}

此外,某些键不具有value属性,因此架构应禁止其与这些键一起出现。这些键之一是“待机”(如您在下面的当前尝试中所见)

我尝试处理this SO answer中的代码示例,但无法使其正常工作。

我目前正在尝试使用Newtonsoft's JSON Schema Validator针对我的模式尝试验证输出json-但似乎无法正确定义“ value”属性。

到目前为止,这是我的代码:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "TestOptionalObject",
    "type": "object",
    "additionalProperties": false,
    "required": [
        "test"
    ],
    "properties": {
        "test": {
            "$ref": "#/definitions/test"
        }
    },
    "definitions": {
        "test": {
            "type": "object",
            "additionalProperties": false,
            "required": [
                "key",
            ],
            "properties": {
                "key": {
                    "type": "string",
                    "enum": ["standby", "comment", "offset"]
                },
                "value" : {
                    "if": {
                        "properties": {
                          "key": {"enum": ["comment"]}
                        }
                    },
                    "then": { 
                        "$ref": "#/definitions/commentValue"
                    },
                    "if": {
                        "properties": {
                          "key": {"enum": ["offset"]}
                        }
                    },
                    "then": { 
                        "$ref": "#/definitions/offsetValue"
                    }
                }
            }
        },
        "commentValue" : {
            "type": "object",
            "additionalProperties": false,
            "required": [
                "text",
            ],
            "properties": {
                "text" : {"type" : "string"}
            }
        },
        "offsetValue" : {
            "type": "object",
            "additionalProperties": false,
            "required": [
                "seconds",
            ],
            "properties": {
                "seconds" : {
                    "type": "integer",
                    "format": "int32"
                }
            }
        }
    }
}

这是我收到的错误消息:

  

JSON与“ then”中的架构不匹配。   架构路径:#/ definitions / offsetValue / then

     

尚未定义属性“文本”,并且该架构不允许其他属性。   架构路径:#/ definitions / offsetValue / additionalProperties

     

对象缺少必需的属性:秒。   架构路径:#/ definitions / offsetValue / required

要验证的Json示例:

应该失败:

{
  "test": {
    "key": "comment",
      "value": {"seconds":12}
  }
}


{
  "test": {
    "key": "standby",
     "value": {"asdf":12}
  }
}

应该通过:

{
  "test": {
    "key": "comment",
     "value": {"text":"comment text"}
  }
}


{
  "test": {
    "key": "offset",
     "value": {"seconds":12}
  }
}

1 个答案:

答案 0 :(得分:1)

我已经更改了JSON模式,所以它可以按您的期望进行操作,除了standby的形式键之外,因为您没有在模式中包含它,并且您应该能够复制我创建的模式到根据需要添加新密钥。

您遇到的主要问题是对if/then/else关键字放置位置的错误假设。它们是应用程序关键字,因此必须应用于要检查其条件的对象,而不是properties键值。由于您在对象中使用if/then/else,其值为value,因此您将if/then/else应用于value的值,而不是test

您需要将if应用于test才能获得检查key属性值的正确范围。

这是生成的固定模式:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "TestOptionalObject",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "test"
  ],
  "properties": {
    "test": {
      "$ref": "#/definitions/test"
    }
  },
  "definitions": {
    "test": {
      "type": "object",
      "required": [
        "key"
      ],
      "properties": {
        "key": {
          "type": "string",
          "enum": [
            "standby",
            "comment",
            "offset"
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "key": {
                "const": "comment"
              }
            }
          },
          "then": {
            "properties": {
              "value": {
                "$ref": "#/definitions/commentValue"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "key": {
                "const": "offset"
              }
            }
          },
          "then": {
            "properties": {
              "value": {
                "$ref": "#/definitions/offsetValue"
              }
            }
          }
        }
      ]
    },
    "commentValue": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "text"
      ],
      "properties": {
        "text": {
          "type": "string"
        }
      }
    },
    "offsetValue": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "seconds"
      ],
      "properties": {
        "seconds": {
          "type": "integer",
          "format": "int32"
        }
      }
    }
  }
}

如果您需要更多帮助,请随时使用http://json-schema.org网站上的讨论链接加入JSON Schema松弛。