如何根据另一个属性的值设置架构对象的类型? [英] how to set the type of a schema object based on the value of another property?

查看:53
本文介绍了如何根据另一个属性的值设置架构对象的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an object (from a 3rd party, so I can't change it) that have a property named "key", and another property called "value" that is optional, and it's type depends on the value of the "key" property.

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

For instance:
If the key is "comment", the type of value {"Text":"commentValue"}.
If the key is "offset", the type of value is {"seconds":int}.
If the key is "weather", the type of value is {"value": Enum["sun", "clouds", "rain"...]}

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

Moreover, some of the keys do not have the value property, so the schema should forbid it from appearing with these keys. one of these keys is "standby" (as you can see in my current attempt below)

我已经尝试处理此SO答案中的代码示例,但无法使其正常工作.

I've tried manipulating the code samples from this SO answer, but couldn't make it work.

我目前正在尝试使用 Newtonsoft的JSON Schema Validator 对我的模式尝试验证输出json -但是我似乎无法正确定义值"属性.

I'm currently attempting to validate output json against my schema attempts using Newtonsoft's JSON Schema Validator - but I can't seem to get the "value" property defined correctly.

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

This is my code so far:

{
    "$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"
                }
            }
        }
    }
}

这是我收到的错误消息:

And this is the error messages I get:

JSON与"then"中的架构不匹配. 架构路径:#/definitions/offsetValue/then

JSON does not match schema from 'then'. Schema path: #/definitions/offsetValue/then

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

Property 'text' has not been defined and the schema does not allow additional properties. Schema path: #/definitions/offsetValue/additionalProperties

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

Required properties are missing from object: seconds. Schema path: #/definitions/offsetValue/required

要验证的Json示例:

Json examples to validate:

应该失败:

{
  "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}
  }
}

推荐答案

我已经更改了JSON模式,因此可以做到您所期望的,除了standby的格式键,因为您没有将其包含在模式中,并且您应该能够复制我创建的模式以根据需要添加新键.

I have changed your JSON Schema so it does what you expect, apart form key of standby as you didn't include that in your schema, and you should be able to replicate the pattern I've created to add new keys as required.

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

The major issue you had was a false assumption about where to place if/then/else keywords. They are applicator keywords, and so must be applied to the object which you are checking the condition of, and not a properties key value. Because you were using if/then/else in the object which was a value of value, you were applying if/then/else to the value of value rather than test.

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

You needed your if to apply to test to get the correct scope for checking the key property 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",
      "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松弛. /json-schema.org 网站.

If you want any more help, please feel free to join the JSON Schema slack using the discussion link on the http://json-schema.org site.

这篇关于如何根据另一个属性的值设置架构对象的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆